---
title: "Rails 6 fixes after_commit callback invocation bug"
description:
  "Rails 6 fixes a bug where after_commit callbacks are called on failed update
  in a transaction block"
canonical_url: "https://www.bigbinary.com/blog/rails-6-fixes-a-bug-where-after_commit-callbacks-are-called-on-failed-update-in-a-transaction-block"
markdown_url: "https://www.bigbinary.com/blog/rails-6-fixes-a-bug-where-after_commit-callbacks-are-called-on-failed-update-in-a-transaction-block.md"
---

# Rails 6 fixes after_commit callback invocation bug

Rails 6 fixes a bug where after_commit callbacks are called on failed update in
a transaction block

- Author: Amit Choudhary
- Published: February 25, 2020
- Categories: Rails 6, Rails

Rails 6 fixes a [bug](https://github.com/rails/rails/issues/29747) where
[after_commit](https://apidock.com/rails/ActiveRecord/Transactions/ClassMethods/after_commit)
callbacks are called on failed update in a transaction block.

Let's checkout the bug in Rails 5.2 and the fix in Rails 6.

#### Rails 5.2

Let's define an
[after_commit](https://apidock.com/rails/ActiveRecord/Transactions/ClassMethods/after_commit)
callback in `User` model and try updating an invalid user object in a
transaction block.

```ruby
>> class User < ApplicationRecord
>>   validates :name, :email, presence: true
>>
>>   after_commit :show_success_message
>>
>>   private
>>
>>     def show_success_message
>>       p 'User has been successfully saved into the database.'
>>     end
>> end

=> :show_success_message

>> user = User.create(name: 'Jon Snow', email: 'jon@bigbinary.com')
begin transaction
User Create (0.8ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Jon Snow"], ["email", "jon@bigbinary.com"], ["created_at", "2019-07-14 15:35:33.517694"], ["updated_at", "2019-07-14 15:35:33.517694"]]
commit transaction
"User has been successfully saved into the database."

=> #<User id: 1, name: "Jon Snow", email: "jon@bigbinary.com", created_at: "2019-07-14 15:35:33", updated_at: "2019-07-14 15:35:33">

>> User.transaction do
>>   user.email = nil
>>   p user.valid?
>>   user.save
>> end
begin transaction
false
commit transaction
"User has been successfully saved into the database."

=> false
```

As we can see here, that that the after_commit callback `show_success_message`
was called even if object was never saved in the transaction.

#### Rails 6.0.0.rc1

Now, let's try the same thing in Rails 6.

```ruby
>> class User < ApplicationRecord
>>   validates :name, :email, presence: true
>>
>>   after_commit :show_success_message
>>
>>   private
>>
>>     def show_success_message
>>       p 'User has been successfully saved into the database.'
>>     end
>> end

=> :show_success_message

>> user = User.create(name: 'Jon Snow', email: 'jon@bigbinary.com')
SELECT sqlite_version(*)
begin transaction
User Create (1.0ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Jon Snow"], ["email", "jon@bigbinary.com"], ["created_at", "2019-07-14 15:40:54.022045"], ["updated_at", "2019-07-14 15:40:54.022045"]]
commit transaction
"User has been successfully saved into the database."

=> #<User id: 1, name: "Jon Snow", email: "jon@bigbinary.com", created_at: "2019-07-14 15:40:54", updated_at: "2019-07-14 15:40:54">

>> User.transaction do
>>   user.email = nil
>>   p user.valid?
>>   user.save
>>   end
false

=> false
```

Now, we can see that after_commit callback was never called if the object was
not saved.

Here is the relevant [issue](https://github.com/rails/rails/issues/29747) and
the [pull request](https://github.com/rails/rails/pull/32185).

## Links

- [Human page](https://www.bigbinary.com/blog/rails-6-fixes-a-bug-where-after_commit-callbacks-are-called-on-failed-update-in-a-transaction-block)
