I'm trying to debug some code. One odd part is that a before_save
callback is getting called twice, though I'm only intending to save the object once.
To trace how this is happening, I've defined these methods in the class:
%w[save save!].each do |method_name|
define_method(method_name) do |*args|
puts "who called '#{method_name}'? #{caller.first}"
super(*args)
end
end
From this output, I only see one persistence call.
I believe that save
and save!
are the only methods that cause ActiveRecord to persist the objects. As far as I know, other persistence methods rely on one of these two; for example, update_attributes
calls save
, update_attributes!
calls save!
, etc.
Do any methods persist an ActiveRecord object without calling save
or save!
?
(I'm using ActiveRecord 3.2.13)
Looking in the Rails source for 3.2.13, both save and save! call the private method create_or_update
to do their work. I used git grep
to look for other occurrences of create_or_update
and only found tests and something in callbacks.rb
that wraps it.
create_or_update
in turn, relies on klass.connection.update
and self.class.unscoped.insert
.
So perhaps the question is whether anything other than create_or_update
persists an ActiveRecord object.
Looking at ActiveRecord 3.2.13 callbacks.rb, line 264. The save callbacks are triggered whenever create_or_update is called. That method is only called by save and save!. update_column bypasses create_or_update and uses update_all instead. first_or_create calls create, which calls save.
I'd be looking in two places: 1. Does the save trigger a save in an associated record that attempts to save the original model again? If so, I'd expect the save method to get called again, so likely not this. 2. Are you sure that the before_save is what is getting called? Assuming you have "before_save :do_something", and do_something is getting called twice. Is anything calling :do_something outside of the context of the save? Or another before_save callback calls :do_something in addition to the callback?
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