Google


   


You are here: CodeIdol.com > Other > Ruby Cookbook > Databases And Persistence > Adding Hooks To Table Events

SAVE
Digg
Shown on del.icio.us del.icio.us
See Whos Talking About This on Technorati Technorati
I've Reddit reddit

Recipe 13.17. Adding Hooks to Table Events

Problem

You want to run some code whenever a database row is added, updated, or deleted. For instance, you might want to send out email whenever a new blog post is created.

Solution

For Og, use the aspect-oriented features of Glue::Aspect. You can use its before and after methods to register code blocks that run before or after any Og method. The methods you're most likely to wrap are og_insert, og_update, and og_delete.

In the following code, I take the BlogPost class first defined in Recipe 13.12, and give its og_insert method an aspect that sends out email:

	require 'cookbook_dbconnect'
	require 'og'
	require 'glue/aspects'

	class BlogPost
	  property :title, :content, String
	  after :on => :og_insert do |post|
	    puts %{Sending email notification of new post "#{post.title}"}
	    # Actually send the email here…
	    end
	end

	og_connect
	post = BlogPost.new
	post.title = 'Robots are taking over'
	post.content = 'Think about it! When was the last time you saw another human?'
	post.save!
	# Sending email notification of new post "Robots are taking over"

This technique works with ActiveRecord as well (since aspect-oriented programming is a generic technique), but ActiveRecord defines two different approaches: callbacks and the ActiveRecord::Observer class.

Any ActiveRecord::Base subclass can define a number of callback methods: before_find, after_save, and so on. These methods run before or after the corresponding ActiveRecord methods. Here's an callback-based ActiveRecord implementation of the Og example, running against the blog_post table first defined in Recipe 13.11. If you ran the previous example in a session, quit it now and start a new session.

	require 'cookbook_dbconnect'
	activerecord_connect

	class BlogPost < ActiveRecord::Base
	  def after_create
	    puts %{Sending email notification of new blog post "#{title}"}
	    # Actually send the email here…
	  end
	end

	post = BlogPost.create(:title => 'Robots: Gentle Yet Misunderstood',
	                       :content => 'Popular misconceptions about robERROR 40')
	# Sending email notification of new blog post "Robots: Gentle Yet Misunderstood

Discussion

ActiveRecord's callback interface is simple, but it's got a big disadvantage compared to Og's. You can attach multiple aspects to a single method, but you can only define a callback method once.

This makes little difference when you only want the callback method to do one thing. But suppose that in addition to sending email whenever a blog post is created, you also want to notify people of new posts through an instant messenger client, and to regenerate static syndication feeds to reflect the new post.

If you used a callback, you'd have to lump all of that code together in after_create. With aspects, each piece of functionality can go into a separate aspect. It's easy to add more, or to disable a single one without affecting the others. Aspects keep auxilliary code from cluttering up your core data classes.

Fortunately, ActiveRecord provides a strategy other than the callback methods. You can define a subclass of ActiveRecord::Observer, which implements any of the callback methods, and use the observe decorator to attach it to the classes you want to watch. Multiple Observers can watch a single class, so you can split up the work.

Here's a third example of the email notification code. Again, start a new session if you're following this recipe in irb.

	require 'cookbook_dbconnect'
	activerecord_connect

	class BlogPost < ActiveRecord::Base
	end

	class MailObserver < ActiveRecord::Observer
	  observe BlogPost
	  def after_create(post)
	    puts %{Sending email notification of new blog post "#{post.title}"}
	    # Actually send the email here.
	  end
	end
	ActiveRecord::Base.observers = MailObserver

	post = BlogPost.new(:title => "ERROR 40",
	                    :content => "ERROR ERROR ERROR ERROR ERROR")
	post.save
	# Sending email notification of new blog post "ERROR 40"

Note the call to ActiveRecord::Base.observers=. Calling this method starts the observer running. You can call ActiveRecord::Base.observers= whenever you need to add one or more Observers. Despite the implication of the method name, calling it twice won't overwrite one set of observers with another.

In a Rails application, observers are traditionally started by putting code like the following in the environment.rb file:

	 # environment.rb
	 config.active_record.observers = MailObserver

When working with ActiveRecord, if you want to attach an Observer to a specific ActiveRecord class, you can name it after that class: for instance, BlogPostObserver will automatically observe the BlogPost class. Obviously, this only works for a single Observer.

See Also


SAVE
Digg
Shown on del.icio.us del.icio.us
See Whos Talking About This on Technorati Technorati
I've Reddit reddit

You are here: CodeIdol.com > Other > Ruby Cookbook > Databases And Persistence > Adding Hooks To Table Events


ADBRITE ads links
   
Related tags







Popular Categories
Unix books and guides

AJAX popular information
C# language guides
Windows books and cookbooks

.......








Business Key Top Sites

be number one
rate your site




    С 2009 года мы стали переводить структура сайта на различные языки. Сайт теперь будет содержать книги не только на английском языке, но также и на других европейских языках, в том числе и на Русском языке.

    Русский Polski Francais Deutsch
    support sitemap terms

© CodeIdol Labs, 2007 - 2009