strange behavior of expire_fragment

I'm following railscasts tutorial on fragment caching, everything works great except for the sweepers. When i put expire_fragment(%r{.*}) directly in my controller, i can expire my fragments with wonderful ease. Yet when i write a nice little sweeper like this code block, nothing gets expired (the puts have been added in for troubleshooting):

class PhraseSweeper < ActionController::Caching::Sweeper     observe Phrase

  def after_update(phrase)     expire_cache(phrase)   end

  def expire_cache(phrase)     puts "=====This Is Activated Via expire_cache(phrase) "     puts expire_fragment(%r{.*}).class     expire_fragment(%r{.*})   end end

I put this put it in apps/sweepers, and initialize the folder under environment.rb. When i update my phrase model I get this in my console:

=====This Is Activated Via expire_cache(phrase) NilClass =====This Is Activated Via expire_cache(phrase) NilClass

Yet when i have the expire_fragment called via my controller i get this in the console:

======This is called via the controller====== Hash

So, my sweeper folder is getting initialized, and the code is running on update, but for some reason the puts are called twice, and the expire_fragment doesn't work at all. Rails 2.1.0 Ruby 1.8.6. Any suggestions??

Have you determined what

   %r{.*}

evaluates to in the context of your Sweeper?

Ar Chron wrote:

Have you determined what

   %r{.*}

evaluates to in the context of your Sweeper?

%r{.*} will delete absoloutly everything in my cache, i think i found my error after reading this forum thread http://www.ruby-forum.com/topic/145163#643061 .

In my controller i had: phrase_sweeper :phrase_sweeper, :only => [:create, :update, :destroy]

when i was actually using an action called :rank_up, for some reason i just assumed if i was updating a model, the :update action would cover it, although i wasn't using :update in my controller. I've yet to try the changes, but i'll let you know the outcome. The confusing part was that the sweeper gets called no mater what, but the expire_fragment only works on the specified actions.

Richard Schneeman wrote:

The confusing part was that the sweeper gets called no mater what, but the expire_fragment only works on the specified actions.

I actually gave up on the sweepers in my app, as they were far too general, and expired more than was necessary in some cases, and given the filters and sorting that can be done, it's all fragment caching.

Now the models decide which of their own fragments to expire (via Rails.cache.delete) depending on what was changed.

Basically, all my controllers inherit from GenericController, all my models from GenericModel, so I can single source stuff like these behaviors, but override if necessary...

GenericController:

def create   model = params[:controller].singularize.downcase   @object = params[:controller].singularize.camelcase.constantize.new(params[model])   if @object.save     # expire caches invalidated by the creation of this object     @object.expire_caches 'create'   end end

def update   model = params[:controller].singularize.downcase   @object = params[:controller].singularize.camelcase.constantize.find(params[:id])   orig_name = @object.name   if @object.update_attributes(params[model])     expire_type = (@object.name == orig_name ? 'update' : 'rename')     # expire caches invalidated by just an update, or an update     # including a name change     @object.expire_caches expire_type   end end

Generic Model:

# models have fragments in basically # modelname.id.row, # modelname.id.show, # modelname.id.related, and a bunch of other 'sub-fragments' # that make up the 'related' items navigation sidebar def expire_caches(method)   model = self.class.table_name.singularize   case method     when 'update'       # just expire the 'show' fragment for this model       expire_base_fragment model, self.id     when 'destroy'       # destroy all the fragments for this model, and all other       # fragments that include this model - this is driven by       # an attribute of each model, which tells what the related       # models are       destroy_caches model, self.id     when 'rename'       # just like destroy       destroy_caches model, self.id     when 'create'       # this case looks at models related to the current       # one to see if those caches should be invalidated. i.e.,       # creating this model as a child of another invalidates       # that models "children" cache       ... ugly code omitted...     else       # there are other actions that can cause different fragments       # to be expired - relating 2 models will cause 4 fragments to       # be expired:       # this model's list of that related type,       # that model's list of this related type,       # and both model's aggregate 'related' fragment       ... ugly code omitted...   end end

The various "expire" or "destroy" methods are all variants of:

def expire_base_fragment(model, id)   Rails.cache.delete('views/'+model+'/'+id.to_s+'/show') end