Skip to content
Browse files

ActiveModel::Callbacks documentation

  • Loading branch information...
1 parent e396683 commit 582228e4355de86ef0a6dc9ce41a3f1da37383f0 @mikel mikel committed Jan 15, 2010
Showing with 101 additions and 47 deletions.
  1. +28 −16 activemodel/README
  2. +73 −31 activemodel/lib/active_model/callbacks.rb
View
44 activemodel/README
@@ -1,21 +1,33 @@
-Active Model
-==============
+= Active Model - defined interfaces for Rails
-Totally experimental library that aims to extract common model mixins from
-ActiveRecord for use in ActiveResource (and other similar libraries).
-This is in a very rough state (no autotest or spec rake tasks set up yet),
-so please excuse the mess.
+Prior to Rails 3.0, if a plugin or gem developer wanted to be able to have
+an object interact with Action Pack helpers, it was required to either
+copy chunks of code from Rails, or monkey patch entire helpers to make them
+handle objects that did not look like Active Record. This generated code
+duplication and fragile applications that broke on upgrades.
-Here's what I plan to extract:
- * ActiveModel::Observing
- * ActiveModel::Callbacks
- * ActiveModel::Validations
+Active Model is a solution for this problem.
- # for ActiveResource params and ActiveRecord options
- * ActiveModel::Scoping
+Active Model provides a known set of interfaces that your objects can implement
+to then present a common interface to the Action Pack helpers.
- # to_json, to_xml, etc
- * ActiveModel::Serialization
+You can include functionality from the following modules:
+
+* Callbacks
+
+ class MyClass
+ extend ActiveModel::Callbacks
+ define_model_callbacks :create
+
+ def create
+ _run_create_callbacks do
+ # Your create action methods here
+ end
+ end
+ end
+
+ ...gives you before_create, around_create and after_create class methods that
+ wrap your create method.
+
+ {Learn more}[link:classes/ActiveModel/CallBacks.html]
-I'm trying to keep ActiveRecord compatibility where possible, but I'm
-annotating the spots where I'm diverging a bit.
View
104 activemodel/lib/active_model/callbacks.rb
@@ -1,50 +1,92 @@
require 'active_support/callbacks'
module ActiveModel
+ # == Active Model Callbacks
+ #
+ # Provides an interface for any class to have Active Record like callbacks.
+ #
+ # Like the Active Record methods, the call back chain is aborted as soon as
+ # one of the methods in the chain returns false.
+ #
+ # 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 call backs attached to:
+ #
+ # define_model_callbacks :create, :update
+ #
+ # This will provide all three standard callbacks (before, around and after) around
+ # both the :create and :update methods. To implement, you need to wrap the methods
+ # you want call backs on in a block so that the call backs get a chance to fire:
+ #
+ # def create
+ # _run_create_callbacks do
+ # # Your create action methods here
+ # end
+ # end
+ #
+ # The _run_<method_name>_callbacks methods are dynamically created when you extend
+ # the <tt>ActiveModel::Callbacks</tt> module.
+ #
+ # Then in your class, you can use the +before_create+, +after_create+ and +around_create+
+ # methods, just as you would in an Active Record module.
+ #
+ # before_create :action_before_create
+ #
+ # def action_before_create
+ # # Your code here
+ # end
+ #
+ # You can choose not to have all three callbacks by passing an 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.
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:
+ # 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
+ #
+ # Note, the <tt>:only => <type></tt> 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 call back 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
- #
- # 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
+ #
+ # class AnotherClass
+ # def self.before_create( obj )
+ # # obj is the MyModel instance that the callback is being called on
# 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)

0 comments on commit 582228e

Please sign in to comment.
Something went wrong with that request. Please try again.