diff options
Diffstat (limited to 'activemodel/lib/active_model/callbacks.rb')
-rw-r--r-- | activemodel/lib/active_model/callbacks.rb | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb new file mode 100644 index 0000000000..f66a1ddcaa --- /dev/null +++ b/activemodel/lib/active_model/callbacks.rb @@ -0,0 +1,91 @@ +require 'active_support/callbacks' + +module ActiveModel + module Callbacks + def self.extended(base) + base.class_eval do + include ActiveSupport::Callbacks + end + end + + # Define callbacks similar to ActiveRecord ones. It means: + # + # * The callback chain is aborted whenever the block given to + # _run_callbacks returns false. + # + # * If a class is given to the fallback, it will search for + # before_create, around_create and after_create methods. + # + # == Usage + # + # First you need to define which callbacks your model will have: + # + # class MyModel + # define_model_callbacks :create + # end + # + # This will define three class methods: before_create, around_create, + # and after_create. They accept a symbol, a string, an object or a block. + # + # After you create a callback, you need to tell when they are executed. + # For example, you could do: + # + # def create + # _run_create_callbacks do + # super + # end + # end + # + # == Options + # + # define_model_callbacks accepts all 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 + # + def define_model_callbacks(*callbacks) + options = callbacks.extract_options! + options = { :terminator => "result == false", :scope => [:kind, :name] }.merge(options) + + types = Array(options.delete(:only)) + types = [:before, :around, :after] if types.empty? + + callbacks.each do |callback| + define_callbacks(callback, options) + + types.each do |type| + send(:"_define_#{type}_model_callback", self, callback) + end + end + end + + def _define_before_model_callback(klass, callback) #:nodoc: + klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + def self.before_#{callback}(*args, &block) + set_callback(:#{callback}, :before, *args, &block) + end + CALLBACK + end + + def _define_around_model_callback(klass, callback) #:nodoc: + klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + def self.around_#{callback}(*args, &block) + set_callback(:#{callback}, :around, *args, &block) + end + CALLBACK + end + + def _define_after_model_callback(klass, callback) #:nodoc: + klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + def self.after_#{callback}(*args, &block) + options = args.extract_options! + options[:prepend] = true + options[:if] = Array(options[:if]) << "!halted && value != false" + set_callback(:#{callback}, :after, *(args << options), &block) + end + CALLBACK + end + end +end
\ No newline at end of file |