2016-09-07 10 views
0

私はRuby on Railsを使ってイベントアプリを構築しています。現時点では、イベントの予約を希望するユーザーは、一度に1つのスペースしか予約および支払えません。私は彼らが複数のスペースを予約し、適切な価格を支払うための施設を提供する必要があります - £10のためにそれぞれ5スペース=支払うために£50など 私はこれをソートするためにRoRの適切なソリューションを探しましたが、レンガの壁。 しかし、私はおそらくこれに間違った方法で近づいてきたと考えています.JavaScriptやjQueryを使用したソリューションが最善の方法です。 私は非常に両方の初心者であり、この目的を達成するための援助が必要です。私は、ユーザーが最初のテキストエリアにし、それに応じて変更する価格(総額)のためのスペースの数を置くことができるようにしたいJavascript/jQuery - 価格計算

Booking page

-

は、ここに私の支払い/予約ページです。

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> 

私が気に入らなかったこのサイトを構築することの1つの側面は、RoRを使用するときにお金を処理することがどれほど難しく複雑であるかです。私が受け取った提案のいくつかは、私はマネタイズ宝石(私はマネーレールを使用していません)を使用するべきであると述べ、これをいくつかのモデルメソッド/ MVCマジックと組み合わせることでこれを達成しました。しかし、適切な解決策が見つかると、私はこのルートを好むだろうと思う。

+0

この 'page:load'イベントは何ですか? 、聞いたことがない – madalinivascu

+0

ストライプの支払い処理に関連しています。 –

答えて

0

お勧めのとおり、1つの方法はJavaScriptを使用して合計を計算することです。

あなたはあなたのビューのこのスニペットを変更することができます:

<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を使ってターゲットにするために、スペースあたりの価格への参照を提供します。たとえば、次のようにJavaScriptを使用して

<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> 

、あなたが入力フィールド上のkeyupイベントをリッスンして計算を行うことができます。

この機能をイベントリスナーから分離すると、ページが読み込まれて開始値を持つように呼び出すこともできます。

Here's a fiddle(これは@event.priceが10であると仮定します)。

UPDATE

ここで重要なのは、@event.priceは、予約の単価を返さなければならないことです。あなたの新しいアクションが、このような単純なことができます:

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 %> 
    ... 

そして、これらの入力(代わりに私のオリジナルのポストでinputspan)を標的とするために、あなたはJavaScriptを調整します。

+0

ありがとうございますが、これを試してみると、イベント価格はゼロとみなされます。私は明らかにイベントの実際の価格を反映するために最初のイベント価格が必要です。 –

+0

間違いなく。 'new'アクションで' @ event'を見つけたら、 '@ event.price'はすでに設定されているはずです。答えにいくつかの詳細を追加しました。 – seancdavis

+0

数量を反映するために予約モデルに何かを追加する必要がありますか?上記の質問には、Rubyを使ってtotal_amountメソッドを試してみるという試みを反映した予約モデルが含まれています。これは今外出する必要がありますか? –

関連する問題