Build vs new в Rails 3

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

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

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

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

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

Ответ 1

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

Ответ 3

Вы правы, сборка и новые функции имеют тот же эффект от установки внешнего ключа, когда они вызываются через ассоциацию. Я полагаю, что причина, по которой документация написана так, заключается в том, чтобы уточнить, что создается экземпляр нового объекта Client, а не новое активное отношение записи. Это тот же эффект, что и вызов .new в классе в Ruby. Иными словами, в документации уточняется, что построение вызова по одной и той же ассоциации - это создание нового объекта (вызов .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

build против new:

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

например:

для нового:

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

Для сборки:

Firm.first.clients.build

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

Ответ 5

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).

Ответ 6

Я не уверен о рубинах на старых версиях rails, но поскольку rails5.0.1, build - это просто псевдоним для нового:

alias build new

Полный код можно найти здесь.

Ниже приведен пример, который показывает, что нет никакой разницы, как build хранит объект в памяти, а новый не будет.

Оба из них сохраняют объект в памяти:

введите описание изображения здесь