2011-02-10 63 views
115

在Rails 3 docs中,關聯的build方法被描述爲與new方法相同,但是具有自動分配外鍵的功能。直接從文檔:構建與新的Rails 3

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

我讀過類似的其他地方。

然而,當我使用new(例如some_firm.clients.new不帶任何參數),新客戶機的關聯firm_id自動創建。我正在控制檯上盯着結果!

我錯過了什麼嗎?文檔有點過時(不太可能)? buildnew有什麼區別?

+3

尋找快速回答的人,請檢查下面的第二個:「構建」只是「新」的別名 – ivanreese 2016-01-21 18:28:20

回答

199

您錯誤地閱讀了文檔。 some_firm.client.new正在從客戶端集合中創建一個新的Client對象,因此它可以自動將firm_id設置爲some_firm.id,而文檔則調用Client.new,它根本不知道任何公司的標識,因此它需要將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(在本例中)保持一致的狀態。

+6

使用`some_firm.client.new`也會將客戶端添加到`some_firm.clients`,並且在`some_firm`上調用`save`導致驗證錯誤,指示'客戶端'無效。如果`new`和`build`都將新客戶端添加到`some_firm`的客戶端集合中,`build`會做些什麼,'new`不會呢?對不起,在這裏! – ClosureCowboy 2011-02-10 14:37:37

+0

我已經在我的文章中添加了一個示例,以更清楚地說明`build`和`new`之間的區別。至於驗證錯誤,我猜你的客戶端模型在保存之前需要更多的數據(例如名稱字段不能爲零)?在這種情況下,您仍然必須在保存之前設置屬性。 – henrym 2011-02-11 00:43:05

11

你是對的,構建和新功能具有相同的設置外鍵的效果,當它們通過關聯被調用時。我相信這樣寫文檔的原因是爲了澄清一個新的Client對象正在被實例化,而不是新的活動記錄關係。這與在Ruby中調用.new的效果相同。也就是說,文檔闡明瞭在關聯上調用構建同樣是創建一個新對象(調用.new)並將外鍵傳遞給該對象。這些命令都是等價的:

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

我相信.build存在的原因是,Firm.first.clients.new可能被解釋爲意味着你正在創建一個新的has_many關係的對象,而不是實際的客戶端,所以調用.build是澄清這一點的一種方式。

+0

因此,它們*是等同的。這絕對是它看起來。謝謝! – ClosureCowboy 2011-02-10 14:49:54

+5

這是不正確的。前兩個在Rails的後續版本中是相同的(看起來在發佈時他們沒有)。但是,最後一個在Firm.first.clients不包含新客戶端方面有顯着差異。 – tybro0103 2014-02-03 18:29:24

3

構建VS新:

主要是新和內部版本是相同的,但建立在內存中存儲對象,

例如。

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

對於構建:

Firm.first.clients.build 

這裏的客戶端存儲在內存中,當保存公司,相關記錄也被保存。

2

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是等價的(因爲導軌3.2至少)。