Skip to content

Commit

Permalink
ActiveModel::Callbacks documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
mikel committed Jan 14, 2010
1 parent e396683 commit 582228e
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 47 deletions.
44 changes: 28 additions & 16 deletions 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.
104 changes: 73 additions & 31 deletions 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)
Expand Down

0 comments on commit 582228e

Please sign in to comment.