I just needed to add a Cache Sweeper in a Rails 3.1 app for a Mongoid model.
Using a ActionController::Caching::Sweeper didn’t run for updates on the models (even though it should work for non-Mongoid-models), so I ended up using a Mongoid::Observer to invalidate the cache when a model was updated.
To seperate the observers from the models, I created a app/observers
directory and used the following code to automatically load the observers:
# mongoid observers/sweepers config.mongoid.observers = Dir["#{config.root}/app/observers/*.rb"].collect do |full_name| File.basename(full_name,'.rb').to_sym end
This is the app/observers/city_observer.rb
file:
class CityObserver < Mongoid::Observer def after_create(city) expire_cache_for(city) end def after_update(city) expire_cache_for(city) end def after_destroy(city) expire_cache_for(city) end private def expire_cache_for(city) # expire fragments/pages for city @c ||= ActionController::Base.new @c.expire_fragment("city_#{city.id.to_s}") if city.state.present? @c.expire_fragment("state_#{city.state.id.to_s}") end if city.country.present? @c.expire_fragment("country_#{city.country.id.to_s}") end # and expire the continent page cache @c.expire_page("/continents/#{city.country.continent.slug}") end end
Since the expire_fragment
/expire_page
functions are not defined in the observer, I create a ActionController::Base
object to call them on that.
With this, a model update expires cached pages