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
(в данном случае) в согласованном состоянии еще до того, как какие-либо объекты были сохранены в базе данных.
Ответ 2
build
- это просто псевдоним для new
:
alias build new
Полный код можно найти по адресу: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74.
Ответ 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 хранит объект в памяти, а новый не будет.
Оба из них сохраняют объект в памяти:
![введите описание изображения здесь]()