0

私はRailsを使ってイベントアプリを構築しています。コントローラのコードブロックをインストールして、イベントのスペースの総数が割り当てられた後に予約が行われないようにしました。 問題は、以前よりも支払いが行われた後にのみ機能するように見えるということです。ユーザーがイベントを予約したときにフラッシュメッセージを表示するコードが必要ですが、現時点ではユーザーが支払い処理を行い、お金を払ってからイベントページにリダイレクトするとフラッシュメッセージが表示されます浮き出る。 また、無料のイベントではなく有料のイベントでのみ動作します。Rails - イベントは完全に予約済み

ここに私のbookings_controllerコードだ -

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

は、このコントローラで調整することができますまたはそれは、モデル内のメソッドを必要とするのか?

+0

あなたのトランザクションブロックはifブロックの後で終了します。これはコピーの貼り付けエラーですか、それとも実際のコードですか? – slowjack2k

+0

これは実際のコードです。 –

+0

予約トランザクションブロックの前に 'if'文**を置こうとしましたか?私の意見では、イベントスペースが利用可能であり、利用可能でない場合にのみ、予約取引に電話してください。 – arjun

答えて

0

Railsは、脂肪モデルとスリムコントローラを推奨しています。これを念頭において、ビジネスロジックをコントローラから抜き取る必要があります。このコードをモデルに入れることができます。

アクションが終了するまでトランザクションを延長することは可能です。何かがうまくいかないときは、エラーが発生し、トランザクションがロールバックされます。いくつかのエラーが発生した場合は、すでに支払いが行われています。

ただし、コードには2つの競合条件があります。最初の競争状態は、ある人がpaypalに送って戻ってきたときから始まった。この時間では、第2の顧客がイベントを予約し、支払っている可能性があり、第2の顧客がpaypalから戻ったときに、このイベントをこれ以上予約することはできません。これは長い時間がかかる可能性があり、顧客を喚起する必要があります。

第2競合状態はここから始まりますif @event.bookings.count > @event.number_of_spacesこのステートメントは複数の要求に対して同時にfalseになることができます。予約が1つしか残っていない場合でも。この場合、あなたは必要に応じてより多くの予約をすることになります。

+0

予約コードでトランザクションコードブロックを適用しますか、それとも別のロジックですか?モデルでこれを行うにはどうすればいいですか? –

+0

この質問は、[コードレビュー](http://codereview.stackexchange.com) – slowjack2k

+1

@ slowjack2kの方が適していると思います。参考までに、あなたは '[sitename.se]'を実行して魔法のリンクを得ることができます。 '[codereview.se]'は[codereview.se] =に変わります) –

関連する問題