2016-11-22 121 views
0

我使用Rails構建一個Event應用程序。我最近改變了我的預訂控制器,以適應免費的活動。應用程序的這一面似乎工作正常,但當我嘗試爲付費活動進行測試預訂時,應用程序在完成付款提交表單後默認爲「預訂不成功」。Rails錯誤 - 訂閱失敗

我不確定爲什麼會發生這種情況。這裏是我的控制器邏輯 -

def new 

     @event = Event.find(params[:event_id]) 
     @booking = Booking.new 
     @booking.user = current_user 



    end 

    def create 
     @event = Event.find(params[:event_id]) 
     @booking = Booking.new(booking_params) 
     @booking.user = current_user 


      if 
       @booking.save 
       flash[:success] = "Your place on our event has been booked" 
       redirect_to event_booking_path(@event, @booking) 
      else 
       flash[:error] = "Booking unsuccessful" 
       render "new" 
      end 

    end 

    def show 
     @event = Event.find(params[:event_id]) 
     @booking = Booking.find(params[:id]) 
    end 


    def update 

     if @booking.update(booking_params) 
      redirect_to event_booking_path(@event, @booking) , notice: "Booking was successfully updated!" 
     else 
      render 'new' 
     end 
    end 




    private 

    def booking_params 
     params.require(:booking).permit(:stripe_token, :booking_number, :quantity, :event_id, :stripe_charge_id, :total_amount) 
    end 

而且在我的模型我有這個 -

Booking.rb

class Booking < ActiveRecord::Base 

    belongs_to :event 
    belongs_to :user 


    before_create :set_booking_number 

    validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 } 
    validates :total_amount, presence: true, numericality: { greater_than_or_equal_to: 0 } 
    validates :quantity, :total_amount, :booking_number, presence: true 

    def set_booking_number 
    self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase 
    end 



    def booking 
     # Don't process this booking if it isn't valid 
     self.valid? 

      if booking.is_free? 
      self.total_amount = event.price_pennies.nil? 
      save! 
      end 



      begin 
         self.total_amount = event.price_pennies * self.quantity 
         charge = Stripe::Charge.create(
          amount: total_amount, 
          currency: "gbp", 
          source: stripe_token, 
          description: "Booking created for amount #{total_amount}") 
         self.stripe_charge_id = charge.id 
       self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase 
         save! 
        rescue Stripe::CardError => e 
        errors.add(:base, e.message) 
        false 
       end 

    end 
end 

所以,由於某種原因,它不保存或還有別的東西不對。任何援助讚賞。

+0

看到錯誤消息對視圖通過顯示驗證錯誤。 'flash [:error] = @ booking.errors.full_messages.join(',')' – usha

+0

您的代碼看起來不完整...不確定您預訂模型中的預訂方法從哪裏調用,但它看起來不是從你的控制器。也可以很方便地看到你的模型中有什麼驗證。 – David

+0

全預訂型號代碼現在添加了驗證。有什麼想法嗎?而不是booking.is_free?它應該是一個帶有event.is_free的if/else語句嗎?那麼'其他'付費方法代碼? (見下面的其他評論) –

回答

0

這是完整的代碼?你的「booking.rb」似乎完全錯誤。

您正在定義一個「預訂」方法,但我沒有看到您在任何地方調用它。 除了可能在預訂法本身,當你執行

if booking.is_free? 

你混的東西了嗎?

+0

你的意思是在控制器?用@ booking.is_free?在這個模型中,我試圖區分免費預訂和付費預訂。在我的事件模型中,我有一個if_free?屬性,但不是在預訂,所以我試圖在這裏分開他們。 –

+0

好的。但在您的Booking.rb中,您定義了一個「預訂」方法,並在第4行中稱您爲「booking.is_free?」但此預訂僅引用方法本身。這就是爲什麼我問代碼是否完整。或者您是否打算調用event.is_free?或某種@ booking.is_free? – Fallenhero

+0

也許是完整的預訂。rb會有幫助 – Fallenhero

0

好的,讓我們來看看。

我想你需要的東西是這樣的:

class Booking < ActiveRecord::Base 

    belongs_to :event 
    belongs_to :user 
    before_create :set_booking_number 
    ### new 
    before_save(:set_total_amount) 

    validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 } 
    validates :total_amount, presence: true, numericality: { greater_than_or_equal_to: 0 } 
    validates :quantity, :total_amount, :booking_number, presence: true 
    ### new 
    validate(:validate_booking) 

    def set_booking_number 
    self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase 
    end 

    def set_total_amount 
    # does event.is_free? exist? if not: either define .is_free? or use self.event.price_pennies.nil? or self.event.price_pennies.to_i == 0 
    if self.event.is_free? 
     # I am guessing total_amount is an Int but you are assigning a boolean 
     # self.total_amount = event.price_pennies.nil? 
     # should be 
     self.total_amount = 0 
    else 
     self.total_amount = event.price_pennies * self.quantity 
     begin 
     charge = Stripe::Charge.create(
      amount: total_amount, 
      currency: "gbp", 
      source: stripe_token, 
      description: "Booking created for amount #{total_amount}") 
     self.stripe_charge_id = charge.id 
     rescue Stripe::CardError => e 
     # if this fails stripe_charge_id will be null, but in case of update we just set it to nil again 
     self.stripe_charge_id = nil 
     # we check in validatition if nil 
     end 
     # booking number was already set, see set_booking_number 
     # self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase 
    end 
    end 

    # is suppose to be a validation, so I renamed it 
    # def booking 
    def validate_booking 
    # Don't process this booking if it isn't valid 
    # will be called on .save anyway 
    # self.valid? 

    # I pushed this to set_total_amount (called by before_save) 
    # if booking.is_free? 
    #  self.total_amount = event.price_pennies.nil? 
    # Why call save! ? with "!" it will cast an exception if invalid 
    #  save! 
    # end 

    # also pushed to set_total_amount since this has nothing to do with validation 
    #  begin 
    #     self.total_amount = event.price_pennies * self.quantity 
    #     charge = Stripe::Charge.create(
    #      amount: total_amount, 
    #      currency: "gbp", 
    #      source: stripe_token, 
    #    description: "Booking created for amount #{total_amount}") 
    #     self.stripe_charge_id = charge.id 
    #  self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase 
    #     save! 
    #    rescue Stripe::CardError => e 
    #    errors.add(:base, e.message) 
    #    false 
    #   end 

    # stripe_charge_id must be set for not free events 
    unless self.event.is_free? 
     return !self.stripe_charge_id.nil? 
    end 
    end 
end 

這當然是未經測試。但請放手。

我希望我的意見很明確。

+0

謝謝你。這一切看起來不錯。我已經對自己的部分內容進行了一些修改,並將其中的一些內容進行了整合 - 上述回答的主要問題是「保存」!需要在控制器中傳遞適當的參數。我會盡快發佈我的最終代碼。 –

0

終於突破了關於參數的一些工作,並在模型代碼上工作。下面是我的控制器和模型最終代碼 -

Booking.rb

class Booking < ActiveRecord::Base 

    belongs_to :event 
    belongs_to :user 
    before_create :set_booking_number 


    validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 } 
    validates :total_amount, presence: true, numericality: { greater_than_or_equal_to: 0 } 

    validate(:validate_booking) 

    def set_booking_number 
    self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase 
    end 

    def set_booking 

    if self.event.is_free? 
     self.total_amount = 0 
     save! 
    else 
     self.total_amount = event.price_pennies * self.quantity 
     begin 
     charge = Stripe::Charge.create(
      amount: total_amount, 
      currency: "gbp", 
      source: stripe_token, 
      description: "Booking created for amount #{total_amount}") 
     self.stripe_charge_id = charge.id 
     save! 
     rescue Stripe::CardError => e 
     self.stripe_charge_id = nil 

     end 
    end 
    end 

    unless self.event.is_free? 
     return !self.stripe_charge_id.nil? 
    end 
    end 
end 

Bookings_controller.rb

class BookingsController < ApplicationController 

    before_action :authenticate_user! 



    def new 
     @event = Event.find(params[:event_id]) 
     # and because the event "has_many :bookings" 
     @booking = Booking.new(params[:booking]) 
     @booking.user = current_user 



    end 

    def create 

     # actually process the booking 
     @event = Event.find(params[:event_id]) 
     @booking = @event.bookings.new(booking_params) 
     @booking.user = current_user 


      if 
       @booking.set_booking 
       flash[:success] = "Your place on our event has been booked" 
       redirect_to event_booking_path(@event, @booking) 
      else 
       flash[:error] = "Booking unsuccessful" 
       render "new" 
      end 

      if @event.is_free? 
       @booking.save(booking_params) 
      end 
    end 

    def show 
     @event = Event.find(params[:event_id]) 
     @booking = Booking.find(params[:id]) 
    end 


    def update 

     if @booking.update(booking_params) 
      redirect_to event_booking_path(@event, @booking) , notice: "Booking was successfully updated!" 
     else 
      render 'new' 
     end 
    end 




    private 

    def booking_params 
     params.require(:booking).permit(:stripe_token, :booking_number, :quantity, :event_id, :stripe_charge_id, :total_amount) 
    end 






end 
+0

那就像你期望的那樣工作? – Fallenhero

+0

是的。迄今爲止都很好。 –