13

I create an infinite callback loop when I need to update an attribute during an after_commit, :on => :create. It only occurs if I need to update an attribute of the object during this callback, though. Is there a way to prevent this? Can I somehow force a model to reload itself so it knows that it is performing an update rather than a create?

class Doc < ActiveRecord::Base
  after_commit :generate, :on => :create

  ...

  def generate
    # some logic here that requires this model to be saved in the db

    self.update_attributes(:filename => filename) # Infinite loop begins here.
  end
end
Alec Sanger
  • 4,442
  • 1
  • 33
  • 53
  • Can you share the server logs generated. Also, it would be great if you share the complete `generate` method. – Kirti Thorat Mar 21 '14 at 19:32
  • I have encountered the same problem, and I think it's a bug. `after_commit` should be trigged only `on: :create` as the declaration, but in fact it's trigged even it's updated. – Sefier Tang Jul 25 '14 at 04:13

3 Answers3

24

You can use the method update_column that will skip all callbacks of your model:

self.update_column(:filename, filename)

Or you could use the method update_all, wich follows the same behavior

self.class.where('id = ?', self.id).update_all(:filename => filename)

And last but not least, my personal favorite:

self.filename = filename
self.send(:update_without_callbacks)

This one makes it pretty clear that all callbacks are been ignored, what is very helpful


Also, as a different alternative, you coud use after_create instead of after_commit if you want to run the generate method only when a new record is saved

  • 1
    Just an FYI, update_without_callbacks was removed in Rails 3. But the first two recommendations still seem to do the trick. – uhezay Jun 11 '15 at 21:29
3

The problem will be update_attributes will initiate the after_commit callback you've used

As mentioned by Rafael, you'd either need to use a callback not triggered by update_attributes, or use an update method which negates callbacks:


update_column does not initiate callbacks - self.update_column(filename: filename)


after_create only fires when you create a record (not update) - after_create :generate

Richard Peck
  • 76,116
  • 9
  • 93
  • 147
0

It's a bug, see the Github issue https://github.com/rails/rails/issues/16286

Sefier Tang
  • 770
  • 3
  • 8
  • 25