346 文字
2 分
AASMでステータス変更と同じクリティカルセクションで実行
概要
- 主にActiveRecordと併用して使うステータス管理用のgemがあります。
- AASM(ステートマシーン)です。
- 「ステータス変更と同時に別の処理を実行したい」という要求を満たすために排他制御(主にデータベースのトランザクション)を使う場面がありますが、どのコールバックを使うのかがAASMのドキュメント内で明示されていなかったので書いておきます。
問題
- よくAASMのサンプルコードで見つけるのが、
after_commitコールバックに処理をしたいメソッドを書く方法です。
https://qiita.com/satour/items/fe838dc21dc95df95c62
-
上記にあるコードでは、ステータスの変更が終わったら通知をするというような別に処理を行っても問題ない処理なのでコードは正しいです。
-
要するに、after_commitはその名の通りAASMによって管理されているステータスが更新されたことをDBにコミットした後に実行されます。
-
しかしながら、AASMで管理するステータスと別のテーブルにあるステータスを同時に更新する場合に
after_commitコールバックを使うだけでは不十分です。
アプローチ
after コールバックを使います。
afterコールバックを使うと、AASMで管理するステートと同じトランザクション内で実行されます。
https://github.com/aasm/aasm/blob/master/lib/aasm/aasm.rb#L177

afterコールバックは、eventとtransitionに対して設定できます。
余談
requires_lock: trueは付ける必要があります。
AASMでステータス変更と同じクリティカルセクションで実行
https://blog.teraren.com/posts/aasm-execute-within-transaction/