ActionController::Caching::Sweeper depends on a controller when trying to expire actions, pages
or fragments but it also invokes itself in contexts where a controller is not initialized. In those contexts,
such as a rails console session, it chooses to return nil in method_missing and more or less fail
silently. If you assumed the cache is bust you'd be wrong.
This is a common problem people run into, because you'd assume it'd "just work". One solution I found
was particularly scary:
ActionController::Base.new.expire_action "…"
in place of letting the Sweeper delegate for you people are actually trying to re-implement the default
behavior of the Sweeper because it is being invoked in contexts that it doesn't try to account for. I decided
to avoid the problem head on and use an Observer with Rails.cache.delete(…) instead, which works without
a controller (and at the cost of some abstraction, but still better). Once you write
ActionController::Base.new.expire_action "…" you are re-implementing the logic of the sweeper, and avoiding
its lookup logic. Something feels wrong if you have to do this. It might be the wrong solution to the problem
but it's also the solution found in the official rails guides.
The sweeper feels broken, its behavior for handling a case where it cannot bust/expire the cache is to silently
fail, and it invokes it self in contexts where it will definitely fail. The silent failure feels like a band aid, and as a
API that people use to implement caching it's obviously confusing. Its promoted as a solution, but really if people
are doing this its better to use an observer & Rails.cache.delete(…) until the Sweeper gets fixed.
What do you guys think? This has annoyed me for a while but finally got around to posting about it.