April 07, 2020
Maybe the easiest way is to start with an example:
class SendsEmail def self.call(email) user = User.new(email: email) user.save EmailSenderJob.perform_async(user.id) end end
Remember that calling
save in an ActiveRecord model is its own
transaction. This means when
EmailSenderJob is called and queued by
our background worker, we don’t even know if the transaction was
What’s the worst thing that could happen?
EmailSenderJob will error out as it wasn’t able to find the
user you provided.
ar_after_transaction provides us with a helper method that accepts
a block — and runs that block only when an open transaction is committed.
The above example can be converted to use
ar_after_transaction by doing:
class SendsEmail def self.call(email) user = User.new(email: email) user.save # Only sends the email when the user is committed to the database ActiveRecord::Base.after_transaction do EmailSenderJob.perform_async(user.id) end end end