0

我正在使用Rails構建事件應用程序。我在我的控制器中安裝了一個代碼塊,以確保一旦該事件的空間總數已被分配/預訂,就不會發生過度預訂。 問題是,它似乎只是在付款後纔開始工作,而不是之前。我需要代碼在用戶點擊預訂該事件時顯示一條Flash消息,但是,目前,它允許用戶完成支付流程,花費他們的錢,然後在重定向到活動頁面時使用閃光消息彈出。 它也只適用於付費活動,而不是免費活動。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並回來的時候。在這段時間內,第二位顧客可以預訂並支付一項活動,並且當第二位顧客從貝寶回來時,不允許再預定此活動。這可能需要很長時間,您應該重新提起客戶。

第二種競賽條件從這裏開始if @event.bookings.count > @event.number_of_spaces這條語句可以是false同時對多個請求。即使只剩下一個預訂。在這種情況下,您最終會得到更多預訂。

+0

我是否在預訂模型中應用交易代碼塊,那麼還是它是不同的邏輯?我該如何去做這個模型? –

+0

我認爲這個問題更適合[code review](http://codereview.stackexchange.com) – slowjack2k

+1

@ slowjack2k僅供參考,你可以通過[[sitename.se]',例如'[codereview.se]'轉向[codereview.se] =) –