web-dev-qa-db-ja.com

ActiveRecordはいつアソシエーションを保存しますか?

1) http://railsapi.com/doc/Rails-v2.3.8/classes/ActiveRecord/AutosaveAssociation.html に従ってautosave: trueのときに関連付けを保存することを知っています

2)次のように構築された関連付けを保存することを知っています

book = Book.new(name: 'foo')
book.authors.build(name: 'bar') #has_many
book.save

またはのような

book = Book.new(name: 'foo')
book.build_author(name: 'bar') #has_one
book.save

3)アソシエーションは、割り当てまたは追加されたときにも保存されると思います

book = Book.new(name: 'foo')
book.author = Author.new(name: 'bar')
book.save

または

book = Book.new(name: 'foo')
book.authors << Author.new(name: 'bar')
book.save

しかし、私はそれが期待するときに自動保存されない何かを含む複雑なバグを持っています。それで、bookを検査してデバッグし、保存されると思われるものが実際に保存されることを確認します。

TL; DR;関連付けを保存するときにチェックされる内部状態は何ですか?モデルにはassociations_to_saveのような内部インスタンス変数があり、関連付けは作成時に追加されると想定しています。次に、モデルが保存されると、それらの関連付けをループして保存します。

34
hrdwdmrbl

残念ながらassociations_to_saveのようなものはありません。ただし、何をいつ保存するかを示すいくつかのルールがあります。ここにあります: http://guides.rubyonrails.org/association_basics.html 。ポイント:4.1.5(belongs_to)、4.2.5(has_one)、4.3.4(has_many)、および4.4.4(habtm)。

更新:

Has_many関連付けの場合、child.new_record?の場合、子は親の保存時に保存されます。 true(子はまだdbに保存されていません)を返すか、foreign_key列を更新する必要があります。これが理由です:

  1. 保存された親の関連付けにオブジェクトを追加すると、新しい子が保存されます。
  2. 未保存の親の関連付けにオブジェクトを追加しても保存されません(外部キー値なし)
  3. 未保存の親が保存され、関連付けキャッシュにいくつかの子オブジェクトがある場合、それらのオブジェクトはforeign_keyを更新するために保存されます。
27
BroiSatse

これが他の人に役立つかどうかはわかりませんが、最近Rails 5.2。

オブジェクトを2層深く保存しようとすると、トップレベルと最初のレベルのオブジェクトが既に保存されている場合、テストは失敗しました。すなわち。

book_cover.persisted? == true
book_cover.book.persisted? == true

page = book_cover.book.pages.new

page.persisted? == false

# After saving the top level object
book_cover.save
page.persisted? == false

# After saving the immediate parent of page
book_cover.book.save
page.persisted? == true

親 "book cover"は新しいオブジェクト "page"の直接の親ではなかったため、 "book cover"を保存しても実際には "page"オブジェクトを保存しませんでした。

状況に応じて、「book」オブジェクトで明示的にsaveを呼び出して、すべての子オブジェクトを保存しました。

2
Matt H