Построить против нового в Rails 3


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

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

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

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

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

5 119

5 ответов:

вы немного неправильно читаете документы. 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 (в данном случае) в согласованном состоянии еще до того, как объекты были сохранены в базе данных.

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

alias build new

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

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

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

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

build vs new:

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

например.

на новый:

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

для сборки:

Firm.first.clients.build

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

модель.новый

Tag.new post_id: 1 будет создать тег post_id set.

@модель.модели.новый

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

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

модели.новые модели против.строй

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