在Rails 3中构建vs新

时间:2011-02-10 07:06:40

标签: ruby-on-rails ruby-on-rails-3 associations

在Rails 3 docs中,关联的build方法被描述为与new方法相同,但是自动分配了外键。直接来自文档:

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

我在其他地方看过类似的内容。

但是,当我使用new(例如some_firm.clients.new没有任何参数)时,会自动创建新客户的firm_id关联 。我现在正在控制台中盯着结果!

我错过了什么吗?文档是否有点过时(不太可能)? buildnew之间的区别是什么?

5 个答案:

答案 0 :(得分:206)

你对这些文档略有误读。 some_firm.client.new正在从clients集合中创建一个新的Client对象,因此它可以自动将firm_id设置为some_firm.id,而文档正在调用Client.new根本不了解任何公司的ID,因此需要firm_id传递给它。

some_firm.clients.newsome_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)

Model.new

Tag.new post_id: 1将使用post_id设置实例化标记。

@ model.models.new

@post.tags.build即使在保存之前,实例化的代码也会在@post.tags中执行相同的 AND

这意味着@post.save将同时保存@post和新构建的标签(假设:设置了inverse_of)。这很好,因为Rails会在保存之前验证这两个对象,如果其中任何一个验证失败,它们都不会被保存。

models.new vs models.build

@post.tags.build@post.tags.new是等效的(至少从Rails 3.2开始)。