Ассоциация own_to не может загрузить целевой родитель, указанный из метода установки при массовом назначении - PullRequest
0 голосов
/ 07 августа 2010

Кажется, что когда дочерний объект имеет ссылку на своего родителя в своем установщике, он не может быть инициализирован, если внешний ключ не указан первым в хэше параметра.

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', ... }

Что действительно раздражает, так это то, что метод build в коллекции has_many тоже не работает, что, я думаю, является правильным местом для исправления, если бы мне пришлось.

Bot.find(1).items.build(:name => 'pitchfork')
# => undefined method `name' for nil:NilClass (NoMethodError)

Какая лучшая идея, чтобы обойти это, или исправить это, или я здесь что-то не так делаю?

1 Ответ

1 голос
/ 07 августа 2010

Вы можете переместить объединяющую строку в обратный вызов after_update. Таким образом, вам не нужно будет обращаться к модели Bot до тех пор, пока она не будет правильно настроена.

Однако я бы, вероятно, оставил name в качестве простой строки, а затем добавил бы виртуальный атрибут для объединенной строки. Таким образом, он также обновляется при изменении имени Bot.

class Item < ActiveRecord::Base
  belongs_to :bot

  def full_name
    @full_name ||= "#{bot.name}'s #{name}"
  end
end
...