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
                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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With