似乎当子对象在其setter中引用其父对象时,除非在参数hash中首先给出外键,否则它无法初始化。
class Bot < ActiveRecord::Base
has_many :items
end
class Item < ActiveRecord::Base
belongs_to :bot
def name=(text)
write_attribute(:name, "#{self.bot.name}'s #{text}")
end
end
Item.new(:name => 'pitchfork', :bot_id => 1, ... )
# => undefined method `name' for nil:NilClass (NoMethodError)
Item.new(:bot_id => 1, :name => 'pitchfork', ... )
# => #<Item id: nil, bot_id: 1, name: "r2d2's pitchfork", ... >
请注意,Ruby 1.9中保留了散列键的顺序,但重点是,bot_id
必须在具有对其父级的引用的访问者之前设置。
因此,以下代码也适用:
item = Item.new
item.bot_id = 1
item.attributes = { :name => 'pitchfork', ... }
令人讨厌的是,has_many集合上的build
方法也不起作用,我认为如果必须的话,我认为这是正确的补丁。
Bot.find(1).items.build(:name => 'pitchfork')
# => undefined method `name' for nil:NilClass (NoMethodError)
最好的办法是解决这个问题,或修补此问题,或者我在这里做错了什么?
答案 0 :(得分:1)
您可以将字符串合并移动到after_update
回调。这样,在正确设置之前,您无需访问Bot
模型。
但是,我可能会将name
保留为一个简单的字符串,然后为合并的字符串添加一个虚拟属性。这样,如果更改Bot
的名称,它也会更新。
class Item < ActiveRecord::Base
belongs_to :bot
def full_name
@full_name ||= "#{bot.name}'s #{name}"
end
end