【问题标题】:Rails error - Booking unsuccessfulRails 错误 - 预订失败
【发布时间】:2016-11-22 14:43:43
【问题描述】:

我正在使用 Rails 构建一个 Event 应用程序。我最近改变了我的预订控制器以容纳免费的活动。应用程序的这一面似乎工作正常,但是当我尝试为付费活动进行测试预订时,在我完成付款提交表单后,应用程序默认为“预订不成功”。

我不太确定为什么会这样。这是我的控制器逻辑 -

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

所以,由于某种原因,它没有保存或有其他不正确的地方。任何帮助表示赞赏。

【问题讨论】:

  • 通过显示验证错误查看错误消息。 flash[:error] = @booking.errors.full_messages.join(',')
  • 您的代码似乎不完整......不确定您在 Booking 模型中的预订方法是从哪里调用的,但它似乎不是来自您的控制器。也可以方便地查看您的模型中有哪些验证。
  • 完整预订模型代码现在添加了验证。有什么想法吗?而不是booking.is_free?它应该是带有 event.is_free 的 if/else 语句吗?那么“其他”付费方法代码? (参见下面的其他 cmets)

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

这是完整的代码吗?您的“booking.rb”似乎完全错误。

您正在定义一个“预订”方法,但我没有看到您在任何地方调用它。 执行时可能在预订方法本身中除外

if booking.is_free?

你是不是把什么东西混在一起了?

【讨论】:

  • 你的意思是在控制器中?使用@booking.is_free?在模型中,我试图区分免费预订和付费预订。在我的事件模型中,我有一个 if_free?属性但不在预订中,所以我试图在这里将它们分开。
  • 好的。但是在您的 Booking.rb 中,您定义了一个方法“booking”,在第 4 行中,您调用了“booking.is_free?”但是这个预订只引用了方法本身。这就是为什么我问代码是否完整。还是您的意思是调用 event.is_free?还是某种@booking.is_free?
  • 也许完整的 Booking.rb 会有所帮助
  • 我正在做一个 if 语句,所以如果它是免费的 - 保存它。如果它不是免费的,请继续前进。但我认为这是问题的症结所在——如何区分免费和付费。
  • 预订模型上唯一的其他代码是一些验证。没有其他方法。
【解决方案2】:

好的,让我们看看。

我认为你需要这样的东西:

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

这当然没有经过测试。不过试试看吧。

我希望我的cmets是清楚的。

【讨论】:

  • 谢谢。一切看起来都不错。我已经实现了自己的一些更改并集成了您的一些更改-上述答案的主要问题是“保存!”需要在控制器中传递正确的参数。我很快就会发布我的最终代码。
【解决方案3】:

终于在参数和模型代码上做了一些工作。这是我的控制器和模型中的最终代码 -

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 2020-01-12
    相关资源
    最近更新 更多