Рубин на рельсах. Как использовать метод Active Record.build в: относится к отношениям?

Мне не удалось найти документацию по методу .build в Rails (в настоящее время я использую 2.0.2).

Посредством экспериментов кажется, что вы можете использовать метод построения, чтобы добавить запись в отношение has_many до того, как была сохранена запись.

Например:

class Dog < ActiveRecord::Base
  has_many :tags
  belongs_to :person
end

class Person < ActiveRecord::Base
  has_many :dogs
end

# rails c
d = Dog.new
d.tags.build(:number => "123456")
d.save # => true

Это сохранит как собаку, так и тэг с внешними ключами правильно. Кажется, что это не работает в отношении belongs_to.

d = Dog.new
d.person.build # => nil object on nil.build

Я также пробовал

d = Dog.new
d.person = Person.new
d.save # => true

Внешний ключ в Dog не установлен в этом случае из-за того, что в момент его сохранения новый человек не имеет идентификатора, потому что он еще не сохранен.

Мои вопросы:

  • Как работает сборка, так что Rails достаточно умен, чтобы выяснить, как сохранить записи в правильном порядке?

  • Как я могу сделать то же самое в отношении belongs_to?

  • Где можно найти документацию по этому методу?

Спасибо

Ответ 1

Где он документирован:

В документации API по ассоциации has_many в разделе Модуль ActiveRecord:: Ассоциации: ClassMethods"

collection.build(attributes = {},...) Возвращает один или несколько новых объектов тип коллекции, которые были созданный с помощью атрибутов и связанные с этим объектом через иностранный ключ, но еще не был сохранены. Примечание. Это работает, только если связанный объект уже существует, а не если это ноль!

Ответ на построение в противоположном направлении - слегка измененный синтаксис. В вашем примере с собаками,

Class Dog
   has_many :tags
   belongs_to :person
end

Class Person
  has_many :dogs
end

d = Dog.new
d.build_person(:attributes => "go", :here => "like normal")

или даже

t = Tag.new
t.build_dog(:name => "Rover", :breed => "Maltese")

Вы также можете использовать create_dog, чтобы он был сохранен мгновенно (так же, как соответствующий метод "create", который вы можете вызвать в коллекции)

Как рельсы достаточно умны? Это волшебство (или, точнее, я просто не знаю, хотелось бы узнать!)

Ответ 2

@article = user.articles.build(:title => "MainTitle")
@article.save