Read my latest article: Six days to complete the Rails hosting survey (posted Thu, 24 Apr 2014 14:36:00 GMT)

Terrific?

Posted by Mon, 30 Apr 2007 22:00:00 GMT

Don’t get me wrong, I really like it when a site takes some initiative and let’s me know as soon as they can if my username is already taken in their system… but I didn’t think that PublicSquare’s approach to letting me know that my username was available… was the sort of feedback that I was looking for.

There is a slight difference between being an available username and being a terrific choice.

Perhaps they are trying to make me feel good about myself? Shrug… I’ll take the compliment (this time).

Okay, now they’re just trying to kiss my…

Q&A: ActiveRecord Observers and You

Posted by Sat, 28 Apr 2007 22:28:00 GMT

Yesterday, I wrote a short post titled, Observers Big and Small, about using Observers in your Rails applications.

The following questions were raised in the comments.

When should I use an Observer?

Eric Allam asks…

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

Eric, this is an excellent question. I’d say that a majority of the time, using the ActiveRecord callbacks in your models is going to work for your situation. However, there are times that you want the same methods to be called through callbacks. For example, let’s take a recent problem that we used an observer to solve.

Graeme is working on implementing Ferret into a project that we’re developing for a client. With the use of Ferret, we can index and later search through content over several objects into a format that makes sense for our implementation goals. Each time an object is created and updated, we have to update our Ferret indexes to reflect these changes. The most obvious location that we can call our indexing methods is in each models’ callbacks, but this violates the DRY[1] principle. So, we created an Observer, which observes each of the models that need these methods to be called. In fact, as far as we’re concerned, the fact that we’re indexing some of its data, is none of its business. We only want our models to be concerned with that they’re designed to be concerned about. We may opt to change our indexing solution in the future and we’d just need to rethink that at the Observer level and not change anything about the business logic in our models.

This is the sort of scenario when using an Observer makes great sense in your application.

Logging from an Observer

Adam R. asks…

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

I assume that you are referring to the logger method? I always forget to even use that method. I do know that the following works just fine in an Observer.


class IndexObserver < ActiveRecord::Observer
  observer Article, Editorial, BlogPost, ClassifiedAd

  def after_save(model)
    RAILS_DEFAULT_LOGGER.warn("Every single day. Every word you say. Every game you play. Every night you stay. I'll be watching you.")
    # execute something fun
  end
end  

This will output to your log file without any problem.

This reminded me of when I used to want to log from Unit Tests.

(few minutes later)

Okay, I just attempted to use logger from an Observer and you’re right… it doesn’t currently work. There is a simple fix though, just extend ActiveRecord::Observer to add a logger method like so and require it in config/environment.rb (much like I did in with unit tests).


# lib/observer_extensions.rb
class ActiveRecord::Observer
  def logger
    RAILS_DEFAULT_LOGGER
  end
end

This will give you a solution to that problem.


class FooObserver < ActiveRecord::Observer
  observer Foo

  def after_save(model)
    logger.warn("I wonder if the #{address.class} knows that I've been watching it all along?")
  end
end  

Observers Spy for Us

Most often, I look at Observers as being the guys that I hire to spy on my models. I don’t want my models to know that they’re being spied on and I’d like to keep it that way. They don’t solve all of our problems and it’s easy to overuse them. However, I have found several cases that they made a lot of sense and most of those cases have been where we’ve had the same things occurring in our model’s callbacks.

If you have other questions related to Observers, feel free to let me know. If you’re already using Observers, perhaps you could post a comment and/or blog post response with an example of when and how you use Observers in your Rails applications.

Related Posts

1 Don’t Repeat Yourself

Observers Big and Small

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

1 comment Latest by Gordon Yeong Tue, 19 Jan 2010 22: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.

Wouldn't it be cool if it?...oh wait.. it already does

Posted by Tue, 24 Apr 2007 04:26:00 GMT

Working into the evening on a client project (been sick and trying to play catchup) and was chatting with Allison about working in views and dummy text. I said, “Just make that a shortcut in TextMate.”

Then I thought, “I can’t be the first person to think of that.”

...as I type, lorem [tab]

Figures. Lorem ipsum generator… in TextMate. Why didn’t I know about this before?

So, I ask all of you… what’s your favorite TextMate trick?

Lately… I’ve been enjoying running single spec files with [apple]-r.

You Might Learn Something at the Back of the Train

Posted by Thu, 19 Apr 2007 16:13:00 GMT

I love to look at other peoples code. Initially, that’s what got me excited about Open Source software. Otherwise, I was looking at small snippets on various developer sites and really not getting the complete picture for how everything tied together.

Last night, I finally had a chance to checkout the sample caboose application, which was created as a way for people to get an idea for how some of developers in caboo.se are putting together their applications.

Some things that you might want to check out it’s using…

It’s definitely worth taking 15 or so minutes to check it out and get some fresh ideas.

There are a few things that I’m not quite sure that didn’t quite make sense, so… perhaps I’ll submit a patch. :-)

svn co svn://caboo.se/plugins/court3nay/empty_apps/tags/v_003

Have fun!

One of those mornings

Posted by Tue, 17 Apr 2007 16:09:00 GMT

Well, I made it about eight months since I got my new hard drive... and today… I had to run…

sudo port -v install mysql5 +server

Why? I have to migrate some data from MySQL to PostgreSQL.

Older posts: 1 2