【问题标题】:Javascript / jQuery - Price calculationJavascript / jQuery - 价格计算
【发布时间】:2016-09-07 11:54:20
【问题描述】:

我正在使用 Ruby on Rails 构建一个事件应用程序。目前,希望预订活动的用户一次只能预订和支付一个空间。我需要为他们提供预订多个空间并支付适当价格的设施 - 所以 5 个空间每个 10 英镑 = 50 英镑支付等。 我已经在 RoR 中寻找合适的解决方案来对此进行排序,但我遇到了障碍。 但是,我相信我可能以错误的方式处理了这个问题,使用 javascript 或 jQuery 的解决方案是最好的方法。 我在这两方面都是新手,需要一些帮助来实现这个目标。

这是我的付款/预订页面 -

我希望用户能够在第一个文本区域中放置空格数并相应地更改价格(总金额)。

这是我的其他相关代码 -

booking.rb -

class Booking < ActiveRecord::Base

    belongs_to :event
    belongs_to :user

    def total_amount

        #quantity.to_i * @price_currency.to_money
        quantity.to_i * strip_currency(event.price)
    end

    private

        def strip_currency(amount = '')
            amount.to_s.gsub(/[^\D\.]/, '').to_f
        end



end

bookings_controller.rb

class BookingsController < ApplicationController

    before_action :authenticate_user!

    def new
        # booking form
        # I need to find the event that we're making a booking on
        @event = Event.find(params[:event_id])
        # and because the event "has_many :bookings"
        @booking = @event.bookings.new(quantity: params[:quantity])
        # which person is booking the event?
        @booking.user = current_user
        #@booking.quantity = @booking.quantity
        @total_amount = @booking.quantity.to_f * @event.price.to_f
    end

    def create
        # actually process the booking
        @event = Event.find(params[:event_id])
        @booking = @event.bookings.new(booking_params)
        @booking.user = current_user
        @price = price
        @quantity = quantity
        #@total_amount = @booking.quantity.to_f * @event.price.to_f

        Booking.transaction do

            @event.reload
            if @event.bookings.count > @event.number_of_spaces
            flash[:warning] = "Sorry, this event is fully booked."
            raise ActiveRecord::Rollback, "event is fully booked"
            end 
        end

        if @booking.save

            # CHARGE THE USER WHO'S BOOKED
            # #{} == puts a variable into a string
            Stripe::Charge.create(amount: @event.price_pennies, currency: "gbp",
                card: @booking.stripe_token, description: "Booking number #{@booking.id}")

            flash[:success] = "Your place on our event has been booked"
            redirect_to event_path(@event)
        else
            flash[:error] = "Payment unsuccessful"
            render "new"
        end

        if @event.is_free?

            @booking.save!
            flash[:success] = "Your place on our event has been booked"
            redirect_to event_path(@event)
        end
    end

    #def total_amount
        #@total_amount = @booking.quantity * @event.price
    #end

    private

      def booking_params
        params.require(:booking).permit(:stripe_token, :quantity)
      end

end

bookings.new.html.erb

<div class="col-md-6 col-md-offset-3" id="eventshow">
  <div class="row">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h2>Confirm Your Booking</h2>
        </div>

            <div class="panel-body">    
                <p>Confirm number of spaces you wish to book here:
                  <input type="number" placeholder="1"  min="1" value="1"></p>
                <p>Total Amount   £<%= @event.price %></p>
                <%= simple_form_for [@event, @booking], id: "new_booking" do |form| %>



                 <span class="payment-errors"></span>

                <div class="form-row">
                    <label>
                      <span>Card Number</span>
                      <input type="text" size="20" data-stripe="number"/>
                    </label>
                </div>

                <div class="form-row">
                  <label>
                  <span>CVC</span>
                  <input type="text" size="4" data-stripe="cvc"/>
                  </label>
                </div>

                <div class="form-row">
                    <label>
                        <span>Expiration (MM/YYYY)</span>
                        <input type="text" size="2" data-stripe="exp-month"/>
                    </label>
                    <span> / </span>
                    <input type="text" size="4" data-stripe="exp-year"/>
                </div>
            </div>
            <div class="panel-footer">    

               <%= form.button :submit %>


            </div> 

<% end %>
<% end %>

      </div>
  </div>
</div>    

<script type="text/javascript" src="https://js.stripe.com/v2/"></script>

<script type="text/javascript">
  Stripe.setPublishableKey('<%= STRIPE_PUBLIC_KEY %>');
  var stripeResponseHandler = function(status, response) {
    var $form = $('#new_booking');

    if (response.error) {
    // Show the errors on the form
    $form.find('.payment-errors').text(response.error.message);
    $form.find('input[type=submit]').prop('disabled', false);
    } else {
    // token contains id, last4, and card type
    var token = response.id;
    // Insert the token into the form so it gets submitted to the server
    $form.append($('<input type="hidden" name="booking[stripe_token]"     />').val(token));
    // and submit
    $form.get(0).submit();
    }
  };

  // jQuery(function($)  { - changed to the line below
  $(document).on("ready page:load", function () {

    $('#new_booking').submit(function(event) {
      var $form = $(this);

      // Disable the submit button to prevent repeated clicks
      $form.find('input[type=submit]').prop('disabled', true);

      Stripe.card.createToken($form, stripeResponseHandler);

      // Prevent the form from submitting with the default action
      return false;
    });
  });
</script>

构建这个网站的一个方面是我不理解的是,在使用 RoR 时处理金钱是多么困难和复杂。我收到的一些建议表明我应该使用货币化 gem(我不是,我正在使用 money-rails),再加上一些模型方法/MVC 魔法可以实现这一点。但是,如果可以找到正确的解决方案,我认为我更喜欢这条路线。

【问题讨论】:

  • 这是什么page:load 事件? ,没听说过
  • 这与条带支付流程有关。

标签: javascript jquery html ruby-on-rails ruby


【解决方案1】:

正如您所建议的,一种方法是使用 JavaScript 来计算总数。

您可以更改视图的这个 sn-p:

<p>
  Confirm number of spaces you wish to book here:
  <input type="number" placeholder="1"  min="1" value="1">
</p>
<p>Total Amount   £<%= @event.price %></p>

使使用 jQuery 更容易定位并提供对每个空间价格的参考。例如:

<div class="calculate-total">
  <p>
    Confirm number of spaces you wish to book here:
    <input type="number" placeholder="1"  min="1" value="1">
  </p>
  <p>
    Total Amount
    £<span class="total" data-unit-cost="<%= @event.price %>">0</span>
  </p>
</div>

使用 JavaScript,您可以在输入字段上侦听 keyup 事件并执行计算。

$('.calculate-total input').on('keyup', calculateBookingPrice);

function calculateBookingPrice() {
  var unitCost = parseFloat($('.calculate-total .total').data('unit-cost')),
      numSpaces = parseInt($('.calculate-total .num-spaces').val()),
      total = (numSpaces * unitCost).toFixed(2);

  if (isNaN(total)) {
    total = 0;
  }

  $('.calculate-total span.total').text(total);
}

将函数与事件侦听器分开意味着您也可以在页面加载时调用它,从而获得起始值。

Here's a fiddle 进行演示(假设@event.price 为10)。

更新

这里的关键是@event.price 应该返回预订的单价。您的 new 操作可以这么简单:

def new
  # Find the event for the booking.
  @event = Event.find(params[:event_id])
  # @event.price should return the unit cost of a booking.

  # Don't need to set attributes here -- you can add them in create.
  @booking = @event.bookings.new
end

还请注意,如果您想在您的 @booking 对象上存储 quantity 和/或 total_amount,您应该移动表单中的字段 (simple_form_for) 并调整标记,以便将它们作为一部分提交的预订。像这样:

<%= simple_form_for [@event, @booking], id: "new_booking" do |form| %>
  <%= f.input :quantity %>
  <%= f.input :total_amount %>
  ...

并调整您的 JavaScript 以定位这些输入(而不是我原来帖子中的 inputspan)。

【讨论】:

  • 谢谢,但是当我尝试这个时,事件价格被假定为零。我显然需要初始活动价格来反映活动的实际价格。
  • 当然。当您在 new 操作中找到 @event 时,应该已经设置了 @event.price。在答案中添加了一些细节。
  • 是否需要在预订模型中添加一些内容以反映数量?我在上面的问题中包含了预订模型,这反映了我尝试使用 Ruby 制定 total_amount 方法。这需要现在出来吗?
  • 以上都不起作用。我仍然以 0.0 作为起点而不是活动价格(对于一个空间),并且在添加数量时它根本没有变化。
  • 我不确定我是否在这里很傻(我是一个真正的 javascript 新手)但是当我看着你的小提琴并添加数量时,总量不会改变 - 它保持不变10 英镑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-01
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多