Сборка против нового в Rails 3 - PullRequest
122 голосов
/ 10 февраля 2011

В Rails 3 docs метод build для ассоциаций описан так же, как метод new, но с автоматическим назначением внешнего ключа. Прямо из документов:

Firm#clients.build (similar to Client.new("firm_id" => id))

Я читал подобное в другом месте.

Однако, когда я использую new (например, some_firm.clients.new без каких-либо параметров), новая клиентская ассоциация firm_id автоматически создается . Я смотрю на результаты прямо сейчас в консоли!

Я что-то упустил? Документы немного устарели (маловероятно)? В чем разница между build и new?

Ответы [ 5 ]

206 голосов
/ 10 февраля 2011

Вы неправильно читаете документы.some_firm.client.new создает новый объект Client из коллекции клиентов, поэтому он может автоматически установить firm_id на some_firm.id, тогда как документы вызывают Client.new, который вообще не знает ни одного идентификатора Фирмы,поэтому ему нужно передать firm_id.

Единственная разница между some_firm.clients.new и some_firm.clients.build, по-видимому, в том, что build также добавляет вновь созданного клиента в коллекцию clients:

henrym:~/testapp$ rails c
Loading development environment (Rails 3.0.4)
r:001 > (some_firm = Firm.new).save # Create and save a new Firm
#=> true 
r:002 > some_firm.clients           # No clients yet
#=> [] 
r:003 > some_firm.clients.new       # Create a new client
#=> #<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil> 
r:004 > some_firm.clients           # Still no clients
#=> [] 
r:005 > some_firm.clients.build     # Create a new client with build
#=> #<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil> 
r:006 > some_firm.clients           # New client is added to clients 
#=> [#<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil>] 
r:007 > some_firm.save
#=> true 
r:008 > some_firm.clients           # Saving firm also saves the attached client
#=> [#<Client id: 1, firm_id: 1, created_at: "2011-02-11 00:18:47",
updated_at: "2011-02-11 00:18:47">] 

Если вы создаете объект с помощью ассоциации, build предпочтительнее, чем new, так как сборка поддерживает ваш объект в памяти, some_firm (в данном случае) в согласованном состояниидаже до того, как какие-либо объекты были сохранены в базе данных.

89 голосов
/ 22 сентября 2012

build это просто псевдоним для new:

alias build new

Полный код можно найти: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74

11 голосов
/ 10 февраля 2011

Вы правы, сборка и новые функции имеют одинаковый эффект установки внешнего ключа, когда они вызываются через ассоциацию.Я полагаю, что причина, по которой документация написана таким образом, состоит в том, чтобы прояснить, что создается новый объект Client, а не новая связь активных записей.Это тот же эффект, который вызовет .new для класса в Ruby.То есть в документации разъясняется, что вызов build для ассоциации - это то же самое, что создание нового объекта (вызов .new) и передача внешних ключей этому объекту.Все эти команды эквивалентны:

Firm.first.clients.build
Firm.first.clients.new
Client.new(:firm_id => Firm.first.id)

Я полагаю, что причина .build в том, что Firm.first.clients.new может интерпретироваться как означающее, что вы создаете новый объект отношения has_many, а не фактическийклиент, так что вызов .build это способ прояснить это.

4 голосов
/ 17 октября 2013

build vs new:

в основном новые и сборки одинаковы, но build сохраняет объект в памяти ,

например:

для новых:

Client.new(:firm_id=>Firm.first.id)

Для сборок:

Firm.first.clients.build

Здесь клиенты хранятся в памяти, при сохранении фирмы также сохраняются связанные записи.

2 голосов
/ 03 февраля 2014

Model.new

Tag.new post_id: 1 создаст экземпляр тега с его установленным post_id.

@model.models.new

@post.tags.build делает то же самое И экземпляр тега будет в @post.tags даже до его сохранения.

Это означает, что @post.save сохранит как @post, так и вновь созданный тег (при условии, что задано значение inverse_of). Это замечательно, потому что Rails проверяет оба объекта перед сохранением, и ни один из них не будет сохранен, если один из них не пройдет проверку.

models.new vs models.build

@post.tags.build и @post.tags.new эквивалентны (по крайней мере, с Rails 3.2).

...