Read my latest article: Was away on vacation (posted Sun, 11 May 2008 22:33:00 GMT)

Observers Big and Small 6

Posted by Robby Russell Fri, 27 Apr 2007 18:15:00 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.

Subscribe to my RSS feed Enjoying the content? Be sure to subscribe to my RSS feed.
Comments

Leave a response

  1. Avatar
    Matt King Fri, 27 Apr 2007 18:51:55 GMT

    This is great to know. I’ve used observers before, mostly in the context of caching views, but not for observing events in models. It seems to me that if you have more than one before_[whatever] or after_[whatever] in your model it’s probably best to move them into an observer. I have a few models that have a ton of these callbacks that will be nice to move out into another location. Thanks!

  2. Avatar
    Eric A. Fri, 27 Apr 2007 18:52:13 GMT

    Why not just use ActiveRecord callback hooks instead of Observers? Are Observers more powerful or is it just a matter of preference?

  3. Avatar
    Adam R. Fri, 27 Apr 2007 23:02:24 GMT

    Yeah, I’d like to know the benefits too. Can you shed some light on this Robby?

    (I’d also like the ability to use the logger from within an observer, but that’s another issue)

  4. Avatar
    Alain Ravet Sun, 29 Apr 2007 07:40:40 GMT

    Eric A

    > Why not just use ActiveRecord callback hooks instead of Observers?
    2 rules of thumb:
    • if a model could become invalid should the triggered action not take place, use AR hooks.
    • if the triggered action modifies the model (ex: pre-render and cache textile text in the model), use AR hooks.

    Otherwise use/consider observers.

  5. Avatar
    sjs Sun, 29 Apr 2007 18:59:26 GMT

    Creating a new record may be cause for some action to be triggered. If that action is tangential to the model which triggers it then it makes sense to keep that action separate. The AR docs have some logical examples that should help you see the point of using observers.

    Observers use the same AR callbacks. You don’t use observers as a replacement for AR callbacks; observers augment the usefulness of the AR callbacks.

  6. Avatar
    Robby Russell Mon, 30 Apr 2007 00:19:36 GMT

    Thanks for the comments!

    I’ve posted a follow up to this article with responses to some of our questions.

Share your thoughts... (really...I want to hear them)

Comments