Jump to content

Ruby on Rails/ActiveRecord/Callbacks

From Wikibooks, open books for an open world

Callbacks

[edit | edit source]

Callbacks provide a means of hooking into an ActiveRecord object's lifecycle.

Implementing Callbacks

[edit | edit source]

There are four types of callbacks accepted by the callback macros:

  • Method references (symbol)
  • Callback objects
  • Inline methods (using a proc)
  • Inline eval methods (using a string) - deprecated.

Method references and callback objects are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for creating mix-ins) and inline eval methods are deprecated.

Method Reference

[edit | edit source]

The method reference callbacks work by specifying a protected or private method available in the object, like this:

  class Topic < ActiveRecord::Base
    before_destroy :delete_parents
    
    private
      def delete_parents
        self.class.delete_all "parent_id = #{id}"
      end
  end

Callback Objects

[edit | edit source]

The callback objects have methods named after the callback, called with the record as the only parameter such as:

  class BankAccount < ActiveRecord::Base
    before_save      EncryptionWrapper.new("credit_card_number")
    after_save       EncryptionWrapper.new("credit_card_number")
    after_initialize EncryptionWrapper.new("credit_card_number")
  end
  
  class EncryptionWrapper
    def initialize(attribute)
      @attribute = attribute
    end
    
    def before_save(record)
      record.credit_card_number = encrypt(record.credit_card_number)
    end
    
    def after_save(record)
      record.credit_card_number = decrypt(record.credit_card_number)
    end
    
    alias_method :after_find, :after_save
    
    private
      def encrypt(value)
        # Secrecy is committed
      end
      
      def decrypt(value)
        # Secrecy is unveiled
      end
  end

So you specify the object you want messaged on a given callback. When that callback is triggered the object has a method by the name of the callback messaged.

Example of using a Proc for a callback:

  class Person
    before_save Proc.new { |model| model.do_something }
  end

Inline Eval

[edit | edit source]

The callback macros usually accept a symbol for the method they’re supposed to run, but you can also pass a "method string" which will then be evaluated within the binding of the callback. Example:

  class Topic < ActiveRecord::Base
    before_destroy 'self.class.delete_all "parent_id = #{id}"'
  end

Notice that single plings (’) are used so the #{id} part isn’t evaluated until the callback is triggered. Also note that these inline callbacks can be stacked just like the regular ones:

  class Topic < ActiveRecord::Base
    before_destroy 'self.class.delete_all "parent_id = #{id}"',
                   'puts "Evaluated after parents are destroyed"'
  end

Callback Reference

[edit | edit source]

before_save

[edit | edit source]

This method is called before an ActiveRecord object is saved.

after_save

[edit | edit source]

Once the active record object saved some method will be fired in that scenario we have to use the after_save callback.

before_create

[edit | edit source]

called before creating a new object of the model

after_create

[edit | edit source]

Called after creating new object and just before saving the records

before_update

[edit | edit source]

after_update

[edit | edit source]

before_validation

[edit | edit source]

after_validation

[edit | edit source]

before_validation_on_create

[edit | edit source]

after_validation_on_create

[edit | edit source]

before_validation_on_update

[edit | edit source]

after_validation_on_update

[edit | edit source]

before_destroy

[edit | edit source]

after_destroy

[edit | edit source]

Partially Documented Callbacks

[edit | edit source]

The following callbacks are partially documented. Their use is discouraged because of [1] performance issues.

after_find

[edit | edit source]

The after_find callback is only executed if there is an explicit implementation in the model class. It will be called for each object returned from a find, and thus can potentially affect performance as noted in the [1] Rails API Documentation.

after_initialize

[edit | edit source]

The after_initialize method is only executed if there is an explicit implementation in the model class. It will be called whenever an ActiveRecord model is initialized. It will be called for each object returned from a find, and thus can potentially affect performance as noted in the [1] Rails API documentation.

References

[edit | edit source]
  1. a b c "Because after_find and after_initialize are called for each object found and instantiated by a finder, such as Base.find(:all), we’ve had to implement a simple performance constraint (50% more speed on a simple test case). Unlike all the other callbacks, after_find and after_initialize will only be run if an explicit implementation is defined (def after_find). In that case, all of the callback types will be called."

=