概要
トランザクションとは分離したいが、保存した内容によって事後処理を行いたい場合がある。
changed?
や hoge_changed?
あたりは save 後には false になってしまうため、更新内容を取得できない。
ApplicationRecord.transaction do if foo.name_changed? # ここでは変更を検知できるけど end foo.save! bar.save! end if foo.name_changed? # ここでは変更を検知できない end
対応
hoge_previously_changed?
を使うと、変更内容を取得できる。
ApplicationRecord.transaction do foo.save! bar.save! end if foo.name_previously_changed?? # 変更を検知できる! end
変更前後の値を比較したり、変更内容を判定したり、まとめて変更を取得できたりもする。
foo.previous_changes # => {"name" => [nil, "Bill"]} foo.name_previously_changed? # => true foo.name_previously_changed?(from: nil, to: "Bill") # => true foo.name_previous_change # => [nil, "Bill"] foo.name_previously_was # => nil
また ID の変更を判定することで、「新規作成か更新か」を区別するという応用もできる。
# true なら新規作成
foo.id_previously_changed?
詳細はドキュメントを参照。
その他
今回のケースでは関係なかったが、 persisted?
というのもあった。
どこかで役に立ちそう。