I feel that observers get a bad rap largely because people lump them in with ActiveRecord lifecycle callbacks as being the same thing. I do agree with a lot of the popular opinion on lifecycle callbacks being easy to misuse, getting yourself in a tangle, but I'm personally a big fan of observers for keeping things out of model classes that are not the particular model's core responsibility. Here's a hint: Rails' observers were partly inspired by aspect-oriented programming -- they're about cross-cutting concerns. If you're putting business logic in observers that is tightly coupled to the models they're observing, you're doing it wrong IMO.
They're ideal for keeping clutter out of model classes, like cache expiration (sweepers), notifications of various sorts, activity stream updates, kicking off background jobs to track custom analytics events, warm caches, etc.
I emphatically disagree with BlueFish about observers being difficult to properly unit test. This is precisely the biggest point that distinguishes them from lifecycle callbacks: you can test observers in isolation, and doing so discourages you from falling into many of the state- and order-heavy design pitfalls BlueFish refers to (which again I think is more often true of lifecycle callbacks).
Here's my prescription:
- Disable all observers in your test suite by default. They should not be complicating your model tests because they should have separate concerns anyway. You don't need to unit test that observers actually fire, because ActiveRecord's test suite does that, and your integration tests will cover it. Use the block form of
ActiveRecord::Base.observers.enable if you really believe there is a good reason to enable an observer for some small piece of your unit tests, but it's likely an indicator of misuse or a design problem.
- Enable observers for your integration tests only. Integration tests of c
answered 2013-02-20T06:09:41.533