概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Rails 6.1 adds support for destroying dependent associations in the background | Saeloun Blog
- 原文公開日: 2020/11/18
- 著者: Prasad Walvekar
- サイト: Saeloun Blog | Ruby on Rails Consulting Company based in San Francisco and Boston
日本語タイトルは内容に即したものにしました。
Rails 6.1: 関連付けをバックグラウンド削除するdependent: :destroy_async
(翻訳)
Railsに組み込まれているdependent:
オプションを使うと、dependent:
に指定したオーナーがdestroyされたときに関連付けられたレコードをどうするかを指定できます。
従来のRailsでは、dependent:
に:destroy
や:delete_all
などの値を渡せます。
:destroy
と:delete_all
は互いによく似通っていますが、唯一の違いは、:delete_all
は関連付けられたオブジェクトをすべて削除するときにコールバックを一切実行しないことです。
訳注:
dependent:
オプションに:destroy
と:delete_all
があるのはhas_many
関連付けの場合です。
has_many
のdependent:
削除系オプション:destroy
または:delete_all
(他のオプションは省略)belongs_to
のdependent:
削除系オプション:destroy
または:delete
(他のオプションは省略)has_one
のdependent:
削除系オプション:destroy
または:delete
(他のオプションは省略)
オブジェクトの関連付けが何層にも積み重なっている大規模なシステムでは、削除のカスケードが失敗することがあります。あるモデルが持つ関連付けが削除されると、それによって他の削除もトリガーされて、複雑なツリーの下まで続く可能性があります。このようなカスケード削除は非常に時間がかかるので、サーバーでタイムアウトエラーが発生するとロールバックする可能性があります。
解決方法: dependent:
オプションに:destroy_async
を指定する
Rails 6.1から、関連付けでdependent:
の値に:destroy_async
を渡せるサポートが追加されました(#40157)。
例
AuthorモデルとBookモデルがあるとします。
以下のように、has_many :books
関連付けのdependent:
オプションに:destroy_async
という値を渡していることにご注目ください。
class Author < ApplicationRecord
has_many :books, dependent: :destroy_async
end
class Book < ApplicationRecord
belongs_to :author
end
たとえばidが1のauthorがBooksモデルの4つのid(1, 2, 3, 4
)に関連付けられているとすると、idが1のauthorを削除したときにRailsが以下のようなジョブを1件作成します。
Performing ActiveRecord::DestroyAssociationAsyncJob (Job ID: 40d5c0cf-ed73-493b-8964-541ae6f1960f) from Async(active_record_destroy) enqueued at 2020-11-16T15:27:00Z with arguments: {:owner_model_name=>”Author”, :owner_id=>1, :association_class=>”Book”, :association_ids=>[1, 2, 3, 4], :association_primary_key_column=>:id,
このジョブが実行されると、Authorモデルにあるそのレコードがデータベースから削除され、以下のようなログが出力されます。
Performed ActiveRecord::DestroyAssociationAsyncJob (Job ID: 40d5c0cf-ed73-493b-8964-541ae6f1960f) from Async(active_record_destroy) in 21.8ms