Saturday, August 25, 2007

Rails callbacks explain

source article

Callbacks


From the API documentation, "Callbacks are hooks into the lifecycle of an Active Record object that allows you to trigger logic before or after an alteration of the object state." There are callbacks for: validate, create, save, update, destroy, find, new/initialize, and associations (Association Callbacks are discussed in the Associations section below).



You may configure most of these callbacks (excluding find, initialize, and association callbacks) in two different ways: (1) overwrite the default method or (2) register with the macros. The macros are more powerful and more commonly used, especially as the macros add their behavior into a callback hierarchy that is maintained through a class inheritance hierarchy. That is, if you register callbacks for the Animal class (which inherits from ActiveRecord::Base) and subsequently define a Monkey class (which inherits from Animal), then Monkey will also inherit the Animal callbacks.



The callback macros can be used in four different ways (see the very clear discussion in the "Types of callbacks" section on the ActiveRecord::Callbacks API page)


  1. symbol reference to a protected or private method in the model

  2. an object to be messaged with the callback method and record

  3. a method string

  4. a method Proc



The validation callback hierarchy



These series are triggered by calls to:
object.valid?

New Record Existing Record
----------------------------- -----------------------------
before_validation before_validation
before_validation_on_create before_validation_on_update
<< object validated here >> << object validated here >>
after_validation after_validation
after_validation_on_create after_validation_on_update



This series is triggered by calls to:
Model.create
object.save (if not previously saved)

before_validation
before_validation_on_create
<< object validated here >>
after_validation
after_validation_on_create
before_save
before_create
<< db record created here >>
after_create
after_save



This series is triggered by calls to:
object.save (if previously saved)
object.update_attributes

before_validation
before_validation_on_update
<< object validated here >>
after_validation
after_validation_on_update
before_save
before_update
<< db record saved/updated here >>
after_update
after_save

A save! call triggers the validation series twice. If save! is called on a new record, the new record validation series with *_on_create methods is called twice.



This series is triggered by calls to:
object.save!

before_validation
before_validation_on_update
<< object validated here >>
after_validation
after_validation_on_update
before_validation
before_validation_on_update
<< object validated here >>
after_validation
after_validation_on_update
before_save
before_update
<< db record saved/updated here >>
after_update
after_save

Several of the save/update methods appear to bypass validation (or at least the validation callbacks) and only call the save callbacks.



This series is triggered by calls to:
object.increment!
object.decrement!
object.toggle!
object.update_attribute

before_save
before_update
<< db record saved/updated here >>
after_update
after_save

The object.update callback hierarchy only triggers the update callbacks.



This series is triggered by calls to:
object.update

before_update
<< db record updated here >>
after_update

However, the model update class method triggers a full series of callbacks.



This series is triggered by calls to:
Model.update

after_find (if defined)
after_initialize (if defined)
before_validation
before_validation_on_update
<< object validated here >>
after_validation
after_validation_on_update
before_save
before_update
<< db record saved/updated here >>
after_update
after_save

increment_counter and decrement_counter bypass all callbacks



These methods bypass all callbacks:
Model.decrement_counter
Model.increment_counter



This series is triggered by calls to:
object.destroy

before_destroy
<< record is deleted here >>
after_destroy

This series is triggered by calls to:
Model.destroy
Model.destroy_all

after_find (if defined)
after_initialize (if defined)
before_destroy
<< record is deleted here >>
after_destroy

These don't trigger any callbacks:
Model.delete
Model.delete_all

The after_find and after_initialize callbacks may will only be called if the default method is overwritten (no macros here).



Triggered by a call to:
Model.new

after_initialize (if defined)

--------------------------------------------

Triggered by a call to:
object.reload
Model.find

after_find (if defined)
after_initialize (if defined)

No comments :