Rails错误 - 预订失败

时间:2016-11-22 14:43:43

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

我正在使用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

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

3 个答案:

答案 0 :(得分:0)

这是完整的代码吗?您的&#34; booking.rb&#34;似乎完全错了。

您正在定义一种方法&#34;预订&#34;,但我没有看到您在任何地方调用它。 执行

时可能在预订方法本身
if booking.is_free?

你有什么东西混在一起吗?

答案 1 :(得分: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

这当然没有经过测试。但试一试。

我希望我的意见很清楚。

答案 2 :(得分:0)

最后突破了对params的一些工作并处理了模型代码。这是我的控制器和模型中的最终代码 -

<强> 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