Reputation: 25682
I've been through the source code for the ActiveRecord callbacks; and I can see the ActiveRecord Concerns for the callbacks like so:
module Callbacks
extend ActiveSupport::Concern
CALLBACKS = [
:after_initialize, :after_find, :after_touch, :before_validation, :after_validation,
:before_save, :around_save, :after_save, :before_create, :around_create,
:after_create, :before_update, :around_update, :after_update,
:before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
]
def destroy #:nodoc:
@_destroy_callback_already_called ||= false
return if @_destroy_callback_already_called
@_destroy_callback_already_called = true
_run_destroy_callbacks { super }
rescue RecordNotDestroyed => e
@_association_destroy_exception = e
false
ensure
@_destroy_callback_already_called = false
end
def touch(*) #:nodoc:
_run_touch_callbacks { super }
end
private
def create_or_update(*)
_run_save_callbacks { super }
end
def _create_record
_run_create_callbacks { super }
end
def _update_record(*)
_run_update_callbacks { super }
end
end
end
Now I can see that the available callbacks via a constant of an array of symbols.
Further investigation shows that the create_or_update(*)
method from the callbacks concern being called from the persistance.rb file (which does the CRUD operations for the model) - and using lines like @_trigger_update_callback = result
.
What I cannot figure out, however is 2 key elements.
How/where does ActiveRecord ACTUALLY trigger the callback, and where is that method that yields to the symbol for the method that you pass to the callback to be executed.
How does ActiveRecord know that the callback even exits? That is, how does it go from being a class declaration, to being executed by ActiveRecord? Is it loaded into some kind of register or something checked each load; etc?
Upvotes: 1
Views: 1520
Reputation: 11070
ActiveRecord and ActiveModel use ActiveSupport::Callbacks to do their dirty work.
If you take a look at its ClassMethods module, you'll find define_callbacks
which is what defines (through module_eval
) _run_update_callbacks
and friends. The _run_*_callbacks
methods just calls run_callbacks
from the main module.
So to answer your questions:
I believe ActiveRecord actually triggers the callbacks in the code you posted. Looks like ActiveRecord::Transactions has a couple that it runs (the transaction related ones, funny enough).
Without digging too deep, it looks like the run_callbacks
method just keeps a list of all the callbacks and then goes through and figures out what's what and what to do.
Probably not as in depth of an answer as you were hoping for, but hopefully this can at least get you going in the right direction digging around and investigating on your own.
Upvotes: 2