Rails 3 docs では、関連付けのbuild
メソッドはnew
メソッドと同じであると説明されていますが、外部キー。ドキュメントから直接:
Firm#clients.build (similar to Client.new("firm_id" => id))
私は他の場所で同様の記事を読みました。
ただし、new
(たとえば、パラメータなしのsome_firm.clients.new
)を使用すると、新しいクライアントのfirm_id
アソシエーションis自動的に作成されます。私は今、コンソールで結果を見つめています!
何か不足していますか?ドキュメントは少し古くなっていますか? build
とnew
の違いは何ですか?
ドキュメントを少し誤解しています。 some_firm.client.new
はクライアントコレクションから新しいClient
オブジェクトを作成しているため、firm_id
をsome_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">]
関連付けを介してオブジェクトを作成している場合は、ビルド前にインメモリオブジェクトsome_firm
(この場合)を一貫性のある状態に保つため、build
よりもnew
を優先する必要があります。オブジェクトはすべてデータベースに保存されています。
build
はnew
の単なるエイリアスです:
alias build new
完全なコードを見つけることができます: https://github.com/Rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74
あなたは正しいです、ビルドと新しい関数は、関連を通して呼び出されるとき、外部キーを設定するのと同じ効果があります。ドキュメントがこのように書かれている理由は、新しいアクティブなレコード関係ではなく、新しい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
対new
:
ほとんどが新しいものとビルドは同じですが、ビルドはメモリにオブジェクトを保存します、
例えば:
新規の場合:
Client.new(:firm_id=>Firm.first.id)
ビルドの場合:
Firm.first.clients.build
ここでは、クライアントがメモリに保存され、会社を保存すると、関連するレコードも保存されます。
Tag.new post_id: 1
は、post_id
が設定されたタグをインスタンス化します。
@post.tags.build
は同じことを行いますおよびインスタンス化されたタグは、保存される前であっても@post.tags
にあります。
これは、@post.save
が@postと新しく構築されたタグの両方を保存することを意味します(:inverse_ofが設定されていると仮定)。 Railsは保存前に両方のオブジェクトを検証し、どちらかが検証に失敗した場合はどちらも保存されないため、これは素晴らしいことです。
@post.tags.build
と@post.tags.new
は同等です(少なくともRails 3.2以降)。