Read my latest article: 8 things I look for in a Ruby on Rails app (posted Thu, 06 Jul 2017 16:59:00 GMT)

Observers Big and Small

Posted by Fri, 27 Apr 2007 17:15:00 GMT

1 comment Latest by Gordon Yeong Tue, 19 Jan 2010 21:43:46 GMT

My colleague, Gary, keeps a stack of Ruby and Rails books on his desk and was implementing an Observer into a client project. It appears that the Agile Web Development with Rails book is still encouraging people to do the following in order to load an Observer.


# app/models/flower_observer.rb
class FlowerObserver < ActiveRecord::Observer
  observe Flower

  def after_create(model)
    # model.do_something!
  end
end

# controller(s)
class FlowerController < ApplicationController
  observer :flower_observer
end

What is wrong with this approach?

Well, in order for your Observer to be used, the model(s) callbacks that it is observing need to be triggered through a controller. If you end up writing any scheduled rake tasks, your observer will not be called. In my opinion, the controller shouldn’t know this much about the model. In fact, the model doesn’t even really know about it’s observer… so why should a controller?

This was actually changed a long time ago (I previously blogged about a different solution here) and the Rails docs for ActiveRecord::Observer are currently correct.

Observers in the Environment

If you open up a recent version of config/environment.rb, you notice in the comments the following.


  # Activate observers that should always be running
  # config.active_record.observers = :cacher, :garbage_collector

Take a moment to go ahead and specify which observer(s) you’d like to load into your Rails environment.

config.active_record.observers = :flower_observer

Then you can remove your observer calls in all your controllers, because that’s not where you should be defining them.

Also, if you’re not using Observers yet, I’d really encourage you to consider reading up on them and giving them a try.

Get help with your Rails project

comments powered by Disqus
Comments
  1. Avatar
    Gordon Yeong Tue, 19 Jan 2010 21:43:46 GMT

    hi, there :) and http://api.rubyonrails.org//

    Good post :)
    I refered to http://guides.rubyonrails.org/action_mailer_basics.html

    I am a bit unclear about observers.

    Consider the set up below:

    model/part_mailer.rb —-—-—-—-—-- class PartMailer < ActionMailer::Base @admin_email = ‘admin@sample.com’ @from_email = ‘admin-sales@sample.com

    def created_succesfully(part)
      recipients user.email, @admin_email
      from @from_email
      subject "MyApp - New part created." 
      body :user => user
    end

    model/part_observer.rb —-—-—-—-—-——

    class PartObserver < ActiveRecord::Observer def after_create(part) PartMailer.deliver_created_succesfully(part) end end

    It looks as if I can only pass in the object of the given class into the observer. In the case above, ‘part’ is the only one that is being passed by to deliver_created_successfully in model/part_observer.rb. part_mailer.rb)? I tried looking at the api docs and http://guides.rubyonrails.org/action_mailer_basics.html to no success. Can someone please shed some light into this?

    Can I pass more objects to the method, created_successfully (model/

    Thanks! :)