Rails 7.2 でトランザクションのコールバックが登録可能になった。

ref. Ruby on Rails 7.2 Release Notes — Ruby on Rails Guides

This is now possible due to a new feature that allows registering transaction callbacks outside of a record.

ActiveRecord::Base.transaction now yields an ActiveRecord::Transaction object, which allows registering callbacks on it.

Article.transaction do |transaction|
  article.update(published: true)

  transaction.after_commit do
    PublishNotificationMailer.with(article: article).deliver_later
  end
end

ActiveRecord::Base.current_transaction was also added to allow to register callbacks on it.

Article.current_transaction.after_commit do
  PublishNotificationMailer.with(article: article).deliver_later
end

これにより、ActiveRecordのコールバックレイヤーではなく、トランザクションのブロックの中で、トランザクションが成功した時(あるいは失敗した時の)コールバック処理が記述可能になった。

具体例としては、処理が成功したらメールを送る、みたいな感じ。

Transaction Callbacks

before_commit, after_rollback でも使える。

ActiveRecord::Base.transaction do |transaction|
  transaction.before_commit { puts "before commit!" }
  transaction.after_commit { puts "after commit!" }
  transaction.after_rollback { puts "after rollback!" }
end

ref. ActiveRecord::ConnectionAdapters::DatabaseStatements | RailsDoc(β)

注意点

When using after_commit callbacks, it is important to note that if the callback raises an error, the transaction won’t be rolled back as it was already committed. Relying solely on these to synchronize state between multiple systems may lead to consistency issues.

ref. ActiveRecord::Transaction | RailsDoc(β)