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