Available for hire
Observers in Rails

In an effort to reduce the clutter of before and after callbacks in your Rails models an Observer can be used. In a simple use case, you may want to give the user 500 credits in your online store when they signup. Without an observer your User model would look something similar to

class User < ActiveRecord::Base
   def before_create
     self.credits = 500
  end
end

Which is fine, if thats all that is in your model. But once your model starts to grow its generally a good idea to keep the callbacks in a different location! Observers to the rescue! With a Rails Observer your code would look similar to

# models/user.rb
class User < ActiveRecord::Base
end

# models/user_observer.rb
class UserObserver < ActiveRecord::Observer
   def before_create(user)
     user.credits = 500
  end
end

Now tell Rails that you want your observer to be included

# config/environment.rb 
Rails::Initializer.run do |config|
  config.active_record.observers = :user_observer
end

Rails will automatically understand that this observer is for the user class based on the name (convention over configuration to the rescue). Although you can also have an observer where the model can’t be inferred by the name, in this case you can explicitly define the models the observer should be observing. For instance, lets say we have an Audit observer, for a number of models.

  class AuditObserver < ActiveRecord::Observer
    observe :user, :item

    def after_update(record)
      AuditTrail.new(record, "UPDATED")
    end
  end

This will observe the user model and on an observed update will create a new audit trail record. Sexy huh? So no excuses, clean your code up, use observers! Its a sexy design pattern which I feel is completely underused!