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
It's a bug, see the Github issue https://github.com/rails/rails/issues/16286
The problem will be
update_attributes
will initiate theafter_commit
callback you've usedAs 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
You can use the method
update_column
that will skip all callbacks of your model:Or you could use the method
update_all
, wich follows the same behaviorAnd last but not least, my personal favorite:
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 ofafter_commit
if you want to run thegenerate
method only when a new record is saved