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

Мне не удалось найти какую-либо документацию по методу .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 не устанавливается в этом случае из-за того, что во время сохранения у нового человека нет идентификатора, поскольку он еще не был сохранен.

Мои вопросы:

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

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

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

Спасибо

Ответы [ 2 ]

145 голосов
/ 24 апреля 2009

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

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

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

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

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", который вы можете вызвать для коллекции)

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

47 голосов
/ 15 декабря 2010
@article = user.articles.build(:title => "MainTitle")
@article.save
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...