A long-lived project that still receives updates
Execute irreversible actions only when transactions are not rolled back
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0
>= 0
>= 0
~> 3
>= 0
~> 1.0

Runtime

>= 6.1.0, < 8.1
 Project Readme

Gem Version CI

Do something only after the currently open transactions have finished.

Normally everything gets rolled back when a transaction fails, but you cannot roll back sending an email or adding a job to Resque.

Install

gem install ar_after_transaction

Usage

just-in-time callbacks

class User
  after_create :do_stuff, :oops

  def do_stuff
    after_transaction do
      send_an_email # cannot be rolled back
    end
    comments.create(...) # will be rolled back
  end

  def oops
    raise "do the rolback!"
  end
end

General 'this should be rolled back when in a transaction' code like jobs

class Resque
  def revertable_enqueue(*args)
    ActiveRecord::Base.after_transaction do
      enqueue(*args)
    end
  end
end

When not in a transaction

after_transaction will perform the given block immediately

Transactional fixtures <-> normally_open_transactions

after_transaction assumes zero open transactions.
If you use transactional fixtures you should change it in test mode.

Rspec:

# spec/rails_helper.rb
  config.before(:suite) do
    ActiveRecord::Base.normally_open_transactions = 1
  end

Adding new rails versions

  • bump in ar_after_transaction.gemspec
  • create a new gemfiles/.gemfile
  • BUNDLE_GEMFILE=gemfiles/<new>.gemfile bundle
  • BUNDLE_GEMFILE=gemfiles/<new>.gemfile bundle exec rake
  • update .github/workflows/actions.yml
  • make a PR

Alternative

Rails 3+

  • basic support is built in, use it if you can!
  • after_commit :foo
  • after_commit :bar, on: :create / :update
  • after_commit everywhere

after_commit

  • pro: threadsafe
  • pro: more fine-grained callbacks (before_commit, after_commit, before_rollback, after_rollback)
  • con: doesn't let you define after_transaction callbacks anywhere like ar_after_transaction does (outside of the after_commit, etc. callbacks which only happen at certain points in the model's life cycle)
  • con: more complex

Authors

Original idea and code from Jamis Buck (post by Jeremy Kemper)

Michael Grosser
michael@grosser.it
License: MIT