Rails 3でのビルドと新規


125

Rails 3のドキュメントではbuild、関連付けのnew方法はメソッドと同じであると説明されていますが、外部キーが自動的に割り当てられます。ドキュメントから直接:

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

私は他の場所でも同様に読みました。

ただし、使用する場合newsome_firm.clients.newパラメーターなしなど)、新しいクライアントのfirm_id関連付け自動的に作成されます。今、コンソールで結果を見つめています!

何か不足していますか?ドキュメントは少し古くなっていますか?違いは何だbuildとはnew


3
簡単な答えを探している人は、2番目の答えを確認してください。「build」は「new」の単なる別名です
ivanreese

回答:


208

ドキュメントを少し読み間違えています。some_firm.client.new新しい作成されたClientクライアントのコレクションからオブジェクトを、それが自動的に設定することができますので、firm_idsome_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優先する必要があります。newsome_firm


8
使用してsome_firm.client.newも、クライアントを追加some_firm.clientsし、呼び出しsavesome_firmそれを示す検証エラーが生じたclient無効でした。両方が新しいクライアントをのクライアントコレクションに追加する場合、newそれは何をしませんか?こんにちは、ごめんなさい!buildsome_firmbuildnew
ClosureCowboy、2011

1
+1 3.0.4で結果を受け取りました。3.0.3の誰かが私が狂っていないことを確認できたら私は大好きです。
ClosureCowboy、2011

41
@henrym 3.2.6のように見えます。clients.newとclients.buildは似ていますが、どちらも新しいオブジェクトをコレクションに追加します。私のようにグーグルでこの問題に遭遇した人にはコメントを追加したかった
ハバード

11
Rails 3.2.3では違いがないようです
Aditya Kapoor

4
この答えは、Rails> 3.2.13では正しくありません。「build」は「new」の単なるエイリアスです。以下の@HatemMahmoudの回答を参照してください。
Andreas 14

91

buildは単なるエイリアスですnew

alias build new

完全なコードは次の場所にあります:https : //github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74


13
alias build newレール3.2.13以降
fontno

7
これは一部の関連/関係にのみ当てはまります。特異協会は、例えば、のための完全に異なる定義が持っているbuildとしますbuild_#{association}こちらこちらをご覧ください。
coreyward 2014

1
これはまだ当てはまりRails 4ますか?
fatman13 14

1
ここにバグレポートがあります...これは、restaurant.customersに追加することなくレストランに関連付けられた新しい顧客を取得する方法として、restaurant.customers.newのようなnewを使用していた場合に、scoped ... .customers.scoped.new
user3334690 '20

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リレーションシップオブジェクトを作成していると解釈される可能性があるためだと思います。


したがって、それら同等です。それは間違いなくそれのようです。ありがとうございました!
ClosureCowboy、2011

5
これは正しくありません。最初の2つは、それ以降のバージョンのRailsでは同等です(投稿した時点ではそうではありませんでした)。しかし、最後のものは、Firm.first.clientsが新しいクライアントを含まないという点で大きな違いがあります。
tybro0103 14

4

buildvs new

ほとんど新しいものとビルドは同じですが、ビルドはオブジェクトをメモリ格納します

例えば:

新規の場合:

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とmodels.build

@post.tags.buildおよび@post.tags.new同等です(少なくともRails 3.2以降)。


これはThe only difference between some_firm.clients.new and some_firm.clients.build seems to be that build also adds the newly-created client to the clients collection:どう?
アレックス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.