在Rails 3 docs中,关联的build
方法被描述为与new
方法相同,但是自动分配了外键。直接来自文档:
Firm#clients.build (similar to Client.new("firm_id" => id))
我在其他地方看过类似的内容。
但是,当我使用new
(例如some_firm.clients.new
没有任何参数)时,会自动创建新客户的firm_id
关联 。我现在正在控制台中盯着结果!
我错过了什么吗?文档是否有点过时(不太可能)? build
和new
之间的区别是什么?
答案 0 :(得分:206)
你对这些文档略有误读。 some_firm.client.new
正在从clients集合中创建一个新的Client
对象,因此它可以自动将firm_id
设置为some_firm.id
,而文档正在调用Client.new
根本不了解任何公司的ID,因此需要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
(在本例中)保持一致即使在将任何对象保存到数据库之前也要说明状态。
答案 1 :(得分:88)
build
只是new
的别名:
alias build new
可以找到完整的代码:https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74
答案 2 :(得分:11)
你是对的,当通过关联调用外,构建和新函数与设置外键具有相同的效果。我认为文档编写的原因是为了澄清新的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是一种澄清这个的方法。
答案 3 :(得分:4)
build
vs new
:
主要是new和build相同但是在内存中构建存储对象,
例如:
for new:
Client.new(:firm_id=>Firm.first.id)
对于构建:
Firm.first.clients.build
此处客户端存储在内存中,当保存公司时,相关记录也会保存。
答案 4 :(得分:2)
Tag.new post_id: 1
将使用post_id
设置实例化标记。
@post.tags.build
即使在保存之前,实例化的代码也会在@post.tags
中执行相同的 AND 。
这意味着@post.save
将同时保存@post和新构建的标签(假设:设置了inverse_of)。这很好,因为Rails会在保存之前验证这两个对象,如果其中任何一个验证失败,它们都不会被保存。
@post.tags.build
和@post.tags.new
是等效的(至少从Rails 3.2开始)。