Rails错误 - 订阅失败

问题描述:

我使用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语句吗?那么'其他'付费方法代码? (见下面的其他评论) –

这是完整的代码?你的“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

好的,让我们来看看。

我想你需要的东西是这样的:

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

谢谢你。这一切看起来不错。我已经对自己的部分内容进行了一些修改,并将其中的一些内容进行了整合 - 上述回答的主要问题是“保存”!需要在控制器中传递适当的参数。我会尽快发布我的最终代码。 –

终于突破了关于参数的一些工作,并在模型代码上工作。下面是我的控制器和模型最终代码 -

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

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