我有这些型号和控制器代码:
class Item < ActiveRecord::Base
has_many :receivers_collateral_items, through: :received_trades, source: :wanted_item
has_many :receivers_wanted_items, through: :received_trades, source: :collateral_item
has_many :requesters_collateral_items, through: :requested_trades, source: :collateral_item
has_many :requesters_wanted_items, through: :requested_trades, source: :wanted_item
validates :year, :price, presence: true, numericality: true
validates :shares, numericality:
{ only_integer: true, greater_than_or_equal_to: 0,
less_than_or_equal_to: :build_shares }
accepts_nested_attributes_for :receivers_collateral_items, :receivers_wanted_items,
:requesters_collateral_items, :requesters_wanted_items,
allow_destroy: true
end
class Trade < ActiveRecord::Base
belongs_to :trade_requester, class_name: "User"
belongs_to :trade_recipient, class_name: "User"
belongs_to :wanted_item, class_name: "Item"
belongs_to :collateral_item, class_name: "Item"
validates :trade_requester, :trade_recipient, :wanted_item, :collateral_item, presence: true
validates :shares, numericality:
{ only_integer: true, greater_than_or_equal_to: 0,
less_than_or_equal_to: :max_shares }
accepts_nested_attributes_for :wanted_item, :collateral_item, allow_destroy: true
def max_shares
if wanted_item.shares > collateral_item.shares
collateral_item.shares
else
wanted_item.shares
end
end
end
class TradesController < ApplicationController
def create
@trade = current_user.requested_trades.build(trade_params)
end
private
def trade_params
params.require(:trade).permit(:trade_requester_id, :trade_recipient_id, :wanted_item_id, :collateral_item_id, :shares)
end
end
但是我得到了 NoMethodError: undefined method 'shares' for nil:NilClass
和一个bd回滚 . 重现错误的步骤:
t = Trade.new
t.trade_requester_id = User.find(1)
t.trade_recipient_id = User.find(2)
t.wanted_item_id = Item.second
t.collateral_item_id = Item.first
t.shares = 100
t.save
堆栈跟踪表明它来自 Trade
中的 numericality
验证,但在我看来,正在调用的类 shares
应该存在 . 我应该能够调用 t.wanted_item
并获得该项目,但我得到 nil
. 但是, t.wanted_item_id
会返回该ID . 为什么是这样?
1 回答
这可能是因为新记录缺少
wanted_item
或collateral_item
. 如果这两个关联中的任何一个返回nil
,那么将抛出异常 . 要解决此问题,请使用旧版本的Rubytry
或Ruby 2.3或更高版本的安全导航操作符(&.
) .这应该解决你的问题(Ruby 2.3之前):
try
方法将返回wanted_item.shares
和collateral_item.shares
的值(如果它们不是nil
) . 如果其中一个是nil
,那么try
将捕获异常并返回nil
.to_i
将nil
转换为零 .因此,如果
collateral_item
存在,collateral_item.try(:shares).to_i
将返回shares
的值,如果collateral_item
是nil
,它将返回零 .如果您使用的是Ruby 2.3或更高版本,则应将
_item.try(:shares).to_i
替换为_item&.shares.to_i
. 后者看起来更干净,faster in execution .Update
对于复制,请确保将记录分配给关联而不是其ID: