DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Custom Rails Callback

03.13.2008
| 6516 views |
  • submit to reddit
        // This shows you how to extend active record to allow a custom callback.

#ever needed to add your own callback into the active record callback chain?
#here's how...
module ActiveRecord
  
  #to keep things clean we'll define our own module
  module SweetCustomCallbacks
    
    #this is the ruby method that is called when you call include on a module
    #the method passed, base in our case, is the class your including yourself in
    def self.included(base)
      
      #this clas_eval method takes a block that will be added to base, which is ActiveRecord::Base
      #basically this is like writing code directly into the class ActiveRecord::Base
      base.class_eval do
        
        #alias_method_chain is very cool
        #it allows us override a method without removing the original and without the original knowing its been changed
        #here's how it works:
        # 1st argument is the name of the method you're overriding
        # 2nd argument is feature you want to add
        # so if create_or_update is called it will actually call create_or_update_with_sweet_custom_callbacks
        # the original is still avaliable at create_or_update_without_custom_callbacks
        
        alias_method_chain :create_or_update, :sweet_custom_callbacks
        #the method create_or_update is an internals method to ActiveRecord that is called whenever you call .save or .update
        
        #this is the class method that allows the cool syntax:
        # class Article < ActiveRecord::Base
        # before_before_save :add_authors_name
        #private
        #def add_authors_name
        #.....
        def self.before_before_save(*callbacks, &block)
          callbacks << block if block_given? #add the block to the array of callback functions if a block was passed
          write_inheritable_array(:before_before_save,callbacks) 
        end
      end
    end
    
    #the instance method, although not recomended is avaliable for overriding
    #also if you wanted to have a callback that always did something say add the users's id to the object 
    #you could always code that in here and remove the class above
    def before_before_save() end

    #ok this is the method that is now called instead of create_or_update
    #it calls a method callback on 
    def create_or_update_with_sweet_custom_callbacks
      return false if callback(:before_before_save) == false  #this method does all the real work and calls the callback function in callbacks.rb that gets the methods and runs them 
      create_or_update_without_sweet_custom_callbacks
    end
    
   end
 
   class Base    
     include SweetCustomCallbacks #include our module in ActiveRecord::Base
   end
end
    

Comments

Snippets Manager replied on Tue, 2008/03/11 - 10:39am

Unfortunately alias_method_chain and write_inheritable_array are Railsisms, so you'd have to implement them yourself if you really wanted to do that. Also callback is a private method in AR::Base.

Snippets Manager replied on Thu, 2007/09/13 - 9:54am

I won't be using this in activerecord (hate rails) - but possibly somewhere else! Really sexy d-: