在Rails 3中构建vs新

Clo*_*boy 123 ruby-on-rails associations ruby-on-rails-3

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

Firm#clients.build (similar to Client.new("firm_id" => id))
Run Code Online (Sandbox Code Playgroud)

我在其他地方读过类似的内容.

然而,当我使用new(例如,some_firm.clients.new不带任何参数),新的客户端的firm_id关联自动创建.我现在正在控制台中盯着结果!

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

hen*_*rym 207

你稍微误读了这些文档.从客户端集合some_firm.client.new创建一个新Client对象,因此它可以自动设置firm_idsome_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">] 
Run Code Online (Sandbox Code Playgroud)

如果您通过关联创建对象,则build应该首选,new因为构建会使您的内存中对象some_firm(在本例中)保持一致状态,甚至在将任何对象保存到数据库之前.

  • @henrym它看起来像3.2.6 clients.new和clients.build类似,它们都将新对象添加到集合中.我希望为任何遇到过这种情况的人添加评论,而谷歌搜索就像我一样 (40认同)
  • 看起来他们在Rails 3.2.3中没有区别 (11认同)
  • 使用`some_firm.client.new`也将客户端添加到`some_firm.clients`,并在`some_firm`上调用`save`导致验证错误,表明`client`无效.如果`new`和`build`都将新客户端添加到`some_firm'的客户端集合中,那么`build`会做什么`new`不能做什么?对不起,我很抱歉! (7认同)
  • 对于Rails> 3.2.13,这个答案是不正确的,其中'build'只是'new'的别名.请参阅下面的@ HatemMahmoud的答案. (4认同)

小智 89

build只是一个别名new:

alias build new
Run Code Online (Sandbox Code Playgroud)

可以找到完整的代码:https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb

  • `alias build new` from rails 3.2.13 (13认同)
  • 这只适用于某些协会/关系.例如,奇异关联对"build"和"build _#{association}"的定义完全不同.见[here](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/singular_association.rb#L28)和[here](https://github.com/rails/轨道/斑点/主/了activerecord/LIB/active_record /协会/助洗剂/ singular_association.rb#L17). (7认同)

Pan*_*kos 11

你是对的,构建和新函数在通过关联调用它们时具有相同的设置外键的效果.我认为文档编写的原因是为了澄清新的Client对象正在被实例化,而不是新的活动记录关系.这与在类中调用.new在Ruby中具有相同的效果.也就是说,文档说明在关联上调用构建是相同的是创建一个新对象(调用.new)并将外键传递给该对象.这些命令都是等效的:

Firm.first.clients.build
Firm.first.clients.new
Client.new(:firm_id => Firm.first.id)
Run Code Online (Sandbox Code Playgroud)

我相信.build存在的原因是Firm.first.clients.new可能被解释为意味着你正在创建一个新的has_many关系对象,而不是一个真正的客户端,因此调用.build是一种澄清这一点的方法.

  • 这是不正确的.前两个在Rails的更高版本中是等效的(看起来在发布时它们不是).但是,最后一个具有显着差异,因为Firm.first.clients将不包含新客户端. (5认同)