Provides an interface for any class to have Active Record like callbacks.
Like the Active Record methods, the callback chain is aborted as soon as one of the methods throws :abort.
First, extend ActiveModel::Callbacks from the class you are creating:
class MyModel extend ActiveModel::Callbacks end
Then define a list of methods that you want callbacks attached to:
define_model_callbacks :create, :update
This will provide all three standard callbacks (before, around and after) for both the :create and :update methods. To implement, you need to wrap the methods you want callbacks on in a block so that the callbacks get a chance to fire:
def create
run_callbacks :create do
# Your create action methods here
end
end
Then in your class, you can use the before_create, after_create and around_create methods, just as you would in an Active Record model.
before_create :action_before_create def action_before_create # Your code here end
When defining an around callback remember to yield to the block, otherwise it won't be executed:
around_create :log_status def log_status puts 'going to call the block...' yield puts 'block successfully called.' end
You can choose to have only specific callbacks by passing a hash to the define_model_callbacks method.
define_model_callbacks :create, only: [:after, :before]
Would only create the after_create and before_create callback methods in your class.
NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
# File activemodel/lib/active_model/callbacks.rb, line 109
def define_model_callbacks(*callbacks)
options = callbacks.extract_options!
options = {
skip_after_callbacks_if_terminated: true,
scope: [:kind, :name],
only: [:before, :around, :after]
}.merge!(options)
types = Array(options.delete(:only))
callbacks.each do |callback|
define_callbacks(callback, options)
types.each do |type|
send("_define_#{type}_model_callback", self, callback)
end
end
end #define_model_callbacks accepts the same options define_callbacks does, in case you want to overwrite a default. Besides that, it also accepts an :only option, where you can choose if you want all types (before, around or after) or just some.
define_model_callbacks :initializer, only: :after
Note, the only: <type> hash will apply to all callbacks defined on that method call. To get around this you can call the #define_model_callbacks method as many times as you need.
define_model_callbacks :create, only: :after define_model_callbacks :update, only: :before define_model_callbacks :destroy, only: :around
Would create after_create, before_update and around_destroy methods only.
You can pass in a class to before_<type>, after_<type> and around_<type>, in which case the callback will call that class's <action>_<type> method passing the object that the callback is being called on.
class MyModel
extend ActiveModel::Callbacks
define_model_callbacks :create
before_create AnotherClass
end
class AnotherClass
def self.before_create( obj )
# obj is the MyModel instance that the callback is being called on
end
end
NOTE: method_name passed to #define_model_callbacks must not end with !, ? or =.
© 2004–2019 David Heinemeier Hansson
Licensed under the MIT License.