Ruby on Rails。:belongs to関係でActive Record .buildメソッドを使用するにはどうすればよいですか?


128

Railsで.buildメソッドに関するドキュメントを見つけることができませんでした(現在2.0.2を使用しています)。

実験により、has_manyいずれかのレコードが保存される前に、buildメソッドを使用して関係にレコードを追加できるようです。

例えば:

class Dog < ActiveRecord::Base
  has_many :tags
  belongs_to :person
end

class Person < ActiveRecord::Base
  has_many :dogs
end

# rails c
d = Dog.new
d.tags.build(:number => "123456")
d.save # => true

これにより、外部キーを持つ犬とタグの両方が適切に保存されます。これはbelongs_to関係で機能していないようです。

d = Dog.new
d.person.build # => nil object on nil.build

私も試しました

d = Dog.new
d.person = Person.new
d.save # => true

Dogこの場合、外部キーは保存されているため、まだ保存されていないため、新しい人物にはIDがありません。

私の質問は:

  1. Railsがレコードを正しい順序で保存する方法を理解できるほどスマートになるように、ビルドはどのように機能しますか?

  2. belongs_to関係で同じことをするにはどうすればよいですか?

  3. この方法に関するドキュメントはどこにありますか?

ありがとうございました


ドキュメントについては、Railsのガイドを参照「で追加されたメソッドbelongs_to「によってメソッドを追加しますhas_one。その他の技術ドキュメントは、APIドキュメント:belongs_toおよびにあり has_oneます。
Dennis

回答:


147

文書化されている場所:

Module ActiveRecord :: Associations :: ClassMethods」のhas_many関連付けの下のAPIドキュメントから

collection.build(attributes = {}、…)属性でインスタンス化され、外部キーを通じてこのオブジェクトにリンクされているが、まだ保存されていないコレクション型の1つ以上の新しいオブジェクトを返します。注:これは、関連付けられたオブジェクトが既に存在する場合にのみ機能し、nilでない場合は機能しません。

反対方向に構築することに対する答えは、わずかに変更された構文です。犬の例では、

Class Dog
   has_many :tags
   belongs_to :person
end

Class Person
  has_many :dogs
end

d = Dog.new
d.build_person(:attributes => "go", :here => "like normal")

あるいは

t = Tag.new
t.build_dog(:name => "Rover", :breed => "Maltese")

create_dogを使用して即座に保存することもできます(コレクションで呼び出すことができる対応する「create」メソッドのように)

レールはどのように十分スマートですか?それは魔法です(より正確には、知りません、知りたいと思います!)


4
@BushyMark:method_missingまたはmetaporgrammingを使用して、define_methodでこれらのメソッドを追加します。
Federico

@Federico不足しているメソッドはどこに定義されていますか?
awilkening

1
@ ActiveRecordのは、あなたのために不足しているメソッドを使用する方法としてalock27と同じfind_by_emailfind_by_column_nameする方法。渡したメソッドを文字列に変換して分析し、テーブルの列名と一致させようとします。
bigpotato 2013年

@edmundコメントありがとうございます。明確にするために、私はmethod_missingの仕組みを理解しています。この特定のメソッドが見つからないことを定義するファイルの実際の場所を見つけようとしました。
awilkening

@ alock27それがどのように定義されているかを調べたいので質問がある場合は、メタプログラミングRubyをチェックしてください。しかし、実際の場所を本当に探しているのであれば、おそらくソースコードをGoogleにすることができます。
MCB 2013年

48
@article = user.articles.build(:title => "MainTitle")
@article.save

>> d.tags.build(:number => "123456")>> d.save#=> true同じではないですか?
Antiqe 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.