Expire_fragment silently does nothing unless you use cache_sweeper?

I’ve run into a very strange problem and I can’t find any docs or any
code in rails core that can explain it.

The behavior is I have a sweeper which is a pure model sweeper so I
tried to use the

config.active_record.observers = [:my_sweeper]

to make it work. However it looks like if I don’t use the
cache_sweeper declaration in the controller, the sweeper gets invoked
but the call to expire_fragment simply does nothing. I found only one
very slight reference to this in a post online -
http://www.ruby-forum.com/topic/145163#643061. But this seems to be a
highly obscure problem. Any ideas?

I put a ‘puts’ call into the rails core expire_cache method and it
appears to never get there…so the logical explanation is that someone
has overridden expire_cache somewhere to make it silently do nothing
and I can’t seem to find where.

The whole point here is that I want my sweepers to act completely
transparently. I don’t want to declare them in every controller. They
should just observe models and act on them. But this behavior is
getting in the way.

thanks!
Yan Pritzker
skwpspace.com

On 5/11/08, skwp [email protected] wrote:

cache_sweeper declaration in the controller, the sweeper gets invoked
The whole point here is that I want my sweepers to act completely
transparently. I don’t want to declare them in every controller. They
should just observe models and act on them. But this behavior is
getting in the way.

CacheSweepers need a controller instance to know how to expire caches.
That’s why the controller filters used by the #cache_sweeper method
in controllers are needed.

I see four solutions:

  • Use #cache_sweeper in every controller that model is modified

  • Add this bit of code to make sure your cache sweepers don’t bomb
    when they fire outside of controller filters:

class MySweeper
def after_save(record)
return if controller.nil?
expire_cache /blah/
end
end

  • Set some #controller to some mock controller object that knows
    enough about routing and ActionController::Caching to expire the cache
    properly. Though this could cause some confusion if people are
    expecting other controller methods to be available too.

  • Use some unique value that changes every time the record is updated
    as part of the cache key.
    http://blog.leetsoft.com/2007/5/22/the-secret-to-memcached Only
    useful for memcache probably.


Rick O.
http://lighthouseapp.com
http://weblog.techno-weenie.net
http://mephistoblog.com