【问题标题】:Rails - NoMethodError undefined method `>=' for nil:NilClassRails - NoMethodError undefined method `>=' for nil:NilClass
【发布时间】:2016-09-29 12:55:48
【问题描述】:

我的模型出现上述错误。这是模型代码-

Booking.rb

    class Booking < ActiveRecord::Base

    belongs_to :event
    belongs_to :user

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

    before_validation :set_default_values_to_greater_than_or_equal_to_zero

    def set_default_values_to_greater_than_or_equal_to_zero
        self.quantity >= 1
        self.total_amount >= 0  
        self.event.price >= 1    unless self.event.is_free
    end

    def reserve(stripe_token)
        # Don't process this booking if it isn't valid
        self.valid?

        # We can always set this, even for free events because their price will be 0.
        #self.total_amount = booking.quantity * event.price

                # Free events don't need to do anything special
                if event.is_free?
                save!

                # Paid events should charge the customer's card
                else

                    begin
                        self.total_amount = event.price * 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
                        save!
                    rescue Stripe::CardError => e
                    errors.add(:base, e.message)
                    false
                end
            end 
        #end
    end
end

在这一行抛出错误代码-

self.quantity >= 1

我相信这是因为此特定列/属性的默认值(或缺少默认值)。在迁移中纠正此问题的正确过程是什么?我是进行 change_column_null 迁移还是 change_column_default ?

这是我的桌子 -

 create_table "bookings", force: :cascade do |t|
    t.integer  "event_id"
    t.integer  "user_id"
    t.string   "stripe_token"
    t.datetime "created_at",       null: false
    t.datetime "updated_at",       null: false
    t.integer  "quantity"
    t.integer  "total_amount"
    t.string   "stripe_charge_id"
  end

显然,没有设置数量(也没有设置总金额)。我试图用 before_validation 回调和下面的方法来纠正这个问题,但它们似乎没有工作。我相信迁移是解决这个问题的唯一方法,对吗?

这是我的控制器代码,我需要在这里输入什么吗?

bookings_controller.rb

 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


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.reserve(booking_params['stripe_token'])
            flash[:success] = "Your place on our event has been booked"
            redirect_to event_path(@event)
        else
            flash[:error] = "Booking unsuccessful"
            render "new"
        end
end


private

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

结束

【问题讨论】:

  • 试试这个,以挽救异常 self.try(:quantity) >= 1
  • 您说“设置”数量,但 ">=" 是比较运算符,而不是赋值运算符。你想在set_default_values_to_greater_than_or_equal_to_zero这个方法中实现什么?另外,我认为该方法应该是私有方法,而不是公共方法。
  • 我试图给数量和总金额一个默认值,所以我没有收到上述错误。此外,如果您进一步记下,我希望用户在预订活动时能够添加多个空间。所以一个空间需要 10 英镑,但他们想预订 5 个空间,因此他们需要支付 50 英镑所以 total_amount = event.price * 数量(需要的空间数量)
  • 您可以根据需要在迁移中定义默认权限。 t.integer "quantity", default: 8

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


【解决方案1】:

如果set_default_values_to_greater_than_or_equal_to_zero 试图为这些属性设置默认值,请将&gt;= 更改为=,因为&gt;= 是一个评估运算符,它将返回truefalse。如果你走这条路,我建议将其设为私有方法。

如果您想进行迁移,则在数据库级别设置默认值(我更喜欢验证前回调),

change_column_default(:bookings, :quantity, 1)

change_column :bookings, :quantity, :integer, :default =&gt; 1

见:

change column default

change column

正如 change_column_default 页面 cmets 中所述,更改列是执行此操作的首选方式

【讨论】:

  • 谢谢。你会建议我也为 total_amount 进行迁移吗?这似乎也没有在预订表中设置默认值。
  • 是的,我会删除该回调和方法。如果这不起作用,请告诉我。
  • 我已经完成了迁移,但现在我得到的错误是“金额必须至少为 30 便士”。可能在这里偏离切线,但这与条纹的数量部分有关吗? (它突出显示了我的模型中的那条线,如上所述)。
  • 是的,它可能在这一行添加了那个错误errors.add(:base, e.message)
  • 看看这是在做什么Stripe::CardError
猜你喜欢
  • 1970-01-01
  • 2020-09-24
  • 2015-03-19
  • 2016-08-13
  • 1970-01-01
  • 2017-07-04
  • 2016-01-02
  • 2012-08-08
  • 2014-09-05
相关资源
最近更新 更多