web-dev-qa-db-ja.com

Rails 3のビルドと新規

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

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

私は他の場所で同様の記事を読みました。

ただし、new(たとえば、パラメータなしのsome_firm.clients.new)を使用すると、新しいクライアントのfirm_idアソシエーションis自動的に作成されます。私は今、コンソールで結果を見つめています!

何か不足していますか?ドキュメントは少し古くなっていますか? buildnewの違いは何ですか?

123
ClosureCowboy

ドキュメントを少し誤解しています。 some_firm.client.newはクライアントコレクションから新しいClientオブジェクトを作成しているため、firm_idsome_firm.idに自動的に設定できますが、ドキュメントはClient.newを呼び出しています会社のIDをまったく知らないため、firm_idを渡す必要があります。

some_firm.clients.newsome_firm.clients.buildの唯一の違いは、buildclientsコレクションに新しく作成されたクライアントを追加することです。

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">] 

関連付けを介してオブジェクトを作成している場合は、ビルド前にインメモリオブジェクトsome_firm(この場合)を一貫性のある状態に保つため、buildよりもnewを優先する必要があります。オブジェクトはすべてデータベースに保存されています。

207
henrym

buildnewの単なるエイリアスです:

alias build new

完全なコードを見つけることができます: https://github.com/Rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74

89
Hatem Mahmoud

あなたは正しいです、ビルドと新しい関数は、関連を通して呼び出されるとき、外部キーを設定するのと同じ効果があります。ドキュメントがこのように書かれている理由は、新しいアクティブなレコード関係ではなく、新しい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関係オブジェクトを作成していることを意味すると解釈される可能性があるためです。

11
Pan Thomakos

buildnew

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

例えば:

新規の場合:

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

ビルドの場合:

Firm.first.clients.build

ここでは、クライアントがメモリに保存され、会社を保存すると、関連するレコードも保存されます。

4
Sarwan Kumar

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は同等です(少なくともRails 3.2以降)。

2
tybro0103