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!