When you start implementing caching mechanisms into your Rails application, you’re going to have to figure out Rails’ Sweepers. These sweepers confused me for a bit and I’d like to offer clarification for anyone else that might have similarly misunderstood the documentation.
From the documentation:
Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change. They do this by being half-observers, half-filters and implementing callbacks for both roles.
The second sentence is what confused me until just today when, while investigating an odd exception email, I dug into the source code. But once I understood what sweepers actually did, the first sentence made even less sense than the second. Further, the example in the documentation is even more misleading. Oh well.
Here’s the scoop: sweepers observe both your models and your controllers. They’re not half-this and half-that, they’re both_. You can define model callbacks (after_save, afterupdate, etc.), and you can also define before/after callbacks for any controller action (e.g. after_list_create).
Here’s the rest of the scoop: if you only define model callbacks, you don’t need to call the cache_sweeper method on your individual controllers. In fact, you may not want to. You can instead add your sweeper directly to config.active_record.observers in your config/environment.rb. There are only two reasons you’d want to call cache_sweeper to register your sweeper: first, if you want to add callbacks to a controller’s actions; and second, if you need access to the current controller in your sweeper’s model-callback methods (justifiable when you need the controller to calculate fragment cache paths, for example). But in the second case, you want to call cache_sweeper from your ApplicationController. Why? Because otherwise you’ll end up observing models that might change from controllers you didn’t explicitely add the cache_sweeper line to, and will eventually rely on a controller variable that doesn’t exist.
Summary:
- Sweepers may implement all ActiveRecord::Observer callbacks. To make these work, you could simply add your sweeper to config.active_record.observers.
- Sweepers may create before/after callbacks for any controller action. To make these work, you need to use the cache_sweeper method on the controllers in question.
- If your sweepers implement model callbacks but need to refer to the controller for any reason, you want to add the cache_sweeper method to the ApplicationController.