Everybody knows that expiring cached pages is like pulling teeth, but regretfully it is something that we all need to do.
One’s first inclination may be to expire pages in the Controller and usually via the update method. Depending on which technique you choose to expire pages you can use the method expire_page {action,fragment}
However, instead of having expired methods around your controllers to clear cache files based on when a model is updated, sweepers are definitely the way to go.
ActionController::Caching::Sweeper class. (Share Objects)
This class is an observer that looks for changes to an object via callbacks, and when a change occurs it expires the caches associated with that object in and around or after filters. The sweeper observes controllers and models.
Hooks:
Any observer callbacks
- after create
- after destroy
- after_save, etc.
Also in any controllers callbacks
- before/after_<controller_name>
- before/after_<controller_name>_<action>
To implement sweepers there are four primary steps.
1) Declare the following load path config.load_paths << “#{RAILS_ROOT}/app/sweepers” in /config/environment.rb. This will keep the sweepers separate from models and controllers.
2) Create the sweepers folder, which contains the observed files.
3) Create the observed files
Note: The observed file should look like the following example:
We can see in the log that the observe gets triggered when a new user is created.
Another way to expire
If we want to avoid using Sweeper we can clear the cache in the model. The following is an example of clearing the cache in the model:
Note: This can also be used in a cron job.
Some Thoughts
* Implementing page caching can be easy. However, expiring can be prove to be a bit more challenging .
* I find testing kind of tricky.
* I read through numerous blog posts but I couldn’t quite figure out how to get things to work as I hoped.
* The following are alternatives I’ve recently used:
* Custom Matches by overwriting the matches? method (ActionController::Caching::Actions)
* Build your CachePage / Fragment Page class and use
ActionController::Base.expire_page( )
ActionController::Caching::Fragments.
expire_fragment
fragment_cache_key
fragment_exist?
read_fragment
write_fragment