Rails does not fire my after_commit callback

rails after_commit
rails skip callbacks
rails callbacks
rails before_validation on: :create
rails before_update
after_commit vs after_save
rails after_save not called
rails after_commit transaction

Hello I have a peculiar problem. I use an after_commit callback to send notifications, but it seems the callback is not triggered at all. Simplified the situation looks like this:

class Message < ActiveRecord::Base
  after_commit :do_something

  def do_something
    raise 'Doing something'
  end
end

Then I expected to see the raise when I open the console and create a message. But nothing happens. Furthermore rails does not even complain if I delete the 'do_something' method completely. Note that this is not a test with transactional fixtures. I even see the record committed in the db. My rails version is 3.0.9. Thanks for any help especially if it's good :-)

Edit: I learned later that the callback DID get triggered when I deployed the code to a different machine. So it must be something with my setup. Still I would appreciate your insight about what could be causing this.

Edit2: From the comments.

  • The DB is MySQL so transactions are present.
  • Specifying the action of the callback did not help (:on => :create).
  • I need after_commit and no other callback

after_commit callback does not fire if the same record got updated , after_commit callback does not fire if the same record got updated The resources of the Rails team are limited, and so we are asking for your  Cat has an after_update callback that will update all its dogs. Dog has an after_commit callback that will print dog barks on destroy. The dog callback will not fire if they got called in the same transaction because ActiveRecord::ConnectionAdapters::Transaction#commit_records method will do uniq on records.

One possible cause (at least on 5.0) is:

after_commit :do_something, on: :create
after_commit :do_something, on: :destroy

here do_something is referenced twice, and none will be executed. Once it is combined to

after_commit :do_something, on: [:create, :destroy]

it would be called again.

after_commit :my_callback, :on => :create fires on update too · Issue , In your gist, you are not saving the updated attribute inside the after_commit, Updating the record, even inside the callback, should not trigger that Rails master: after_commit(on: :update) is executed erroneously when a  Updating the record, even inside the callback, should not trigger that particular after_commit callback again, due to its :on => :create option. It only run once at creation, the problem is the save inside the callback that will result in an infinite loop.

You may need to put a patch in your spec/support to enable after_commit callbacks when using transactional fixtures. If you are using transaction fixtures then a commit doesn't actually ever happen.

The patch: https://gist.github.com/charleseff/1305285

Active Record Callbacks, This guide teaches you how to hook into the life cycle of your Active Record objects. Callbacks can also be registered to only fire on certain life cycle events​: The code executed within after_commit or after_rollback callbacks is itself not​  after_commit fires on create, update and destroy. The main difference is after_save invokes immediately after the model object save method completes, where after_commit doesn't fire until record is actually committed to the DB.

You should specify the action when this after_commit must be triggered....

The after_commit is basically used in those Databases where the concept of transaction is present...So try the following code...

class Message < ActiveRecord::Base
 after_commit :do_something, :on => [:create, :update, :destroy]

 def do_something
  raise 'Doing something'
 end
end

Rails < 5: How to get after_commit callbacks fired in tests , Rails 5 has a fix for this issue and no further action is needed. Rails 3+. Add the gem test_after_commit to your test group in the Gemfile and you are done. You don  Most of these validations execute in the order they are defined. For example, if you have two before_save callbacks defined, then they will execute one after the other. However there are two callbacks that do not execute in this order - after_commit and after_rollback.

Try if below code helps -

class Message < ActiveRecord::Base
 after_commit :do_something, :only => [:create, :update, :destroy]

 def do_something
  raise 'Doing something'
 end
end

A couple of callback gotchas (and a Rails 5 fix), But this also means your after_commit callback won't run. Because after_commit callbacks only run when the outermost transaction has been  The call to after_update_commit does override the callback added by after_create_commit, because under the hood they both set after_commit callbacks with different conditions. However the after_*_commit aliases look like they're implemented as distinct callbacks, which is confusing to the point where it could probably be considered a bug.

The unexpected after_commit behaviour, and after_destroy_commit behave in a way you may not expect. The after_commit callback is a well-known part of the Ruby on Rails framework. It's the primary method to use if we want to trigger a background job associated with a Subscribe to get my content on web development, programming,  Ruby on Rails. Contribute to rails/rails development by creating an account on GitHub.

How to Safely Use ActiveRecord's after_save, If you've used Ruby on Rails for any period of time, you understand the pain and database state in the callbacks after_commit and after_rollback . Don't put your code in these callbacks if you do not want this Any query made directly in SQL or through another application will not trigger your callbacks. The reported problem was an after_commit callback being erroneously called in a similar test case, but the fix and the test for it are ensuring that the after_rollback callback is also prevented from running. So if the existing test is correct, then the behavior shown in this issue is intended. If not, I can attempt a fix and a cleanup of the test.

Execution order of after_commit and after_rollback ActiveRecord , Knowing the order of how your callbacks fire is important to Rails allows the adding of various callbacks that trigger during the lifecycle However there are two callbacks that do not execute in this order - after_commit and  Any exception that is not ActiveRecord::Rollback will be re-raised by Rails after the callback chain is halted. Raising an exception other than ActiveRecord::Rollback may break code that does not expect methods like save and update_attributes (which normally try to return true or false) to raise an exception.

Comments
  • How you are creating the model in the console?
  • I tried it via a factory and also via a save and save! call.
  • As I understand all of them should trigger the callback. I also tried it from a production console.
  • Try logging in your after_commit instead of raising. Rails rescues nil from any after_commit hook being called.
  • It's not your fault, it's a bug in Rails
  • For 4.0 the last declared after_commit will work. In this case the destroy.
  • The Gist is already packed as gem and working too github.com/grosser/test_after_commit
  • Thought so too, but it didn't help.
  • Right, I forgot to mention that the DB is MySQL.
  • I think it should not matter a lot becoz MySQL and Sqlite both support the transactions and if it is not running on MySQL then it would not run SQLite also...but still you can give it a try and let me know the results...
  • Nno, this did not help. See the second edit of the question. But thanks anyway.
  • I specifically need after_commit, because after_create can get executed BEFORE the record is actually committed in the db so that the other connections can also read it. And if you send a notification to some other device with an id of the record and the record is not yet there -> nothing happens.