belongs_to关联无法加载从质量赋值的setter方法引用的目标父级

时间:2010-08-07 15:52:54

标签: ruby-on-rails activerecord foreign-keys associations

似乎当子对象在其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)

最好的办法是解决这个问题,或修补此问题,或者我在这里做错了什么?

1 个答案:

答案 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