24

I'm using Memcached with Heroku for a Rails 3.1 app. I had a bug and the wrong things are showing - the parameters were incorrect for the cache.

I had this:

<% cache("foo_header_cache_#{@user.id}") do %> 

I removed the fragment caching and pushed to Heroku and the bad data went away.

And then I changed it to:

<% cache("foo_header_cache_#{@foo.id}") do %> 

However, when I corrected the parameters, from @user to @foo, the old [incorrect] cached version showed again (instead of refreshing with the correct data).

How can I manually expire this, or otherwise get rid of this bad data that is showing?

yellowreign
  • 3,528
  • 8
  • 43
  • 80

4 Answers4

44

I ended up manually clearing the entire cache by going into the rails console and using the command:

Rails.cache.clear
yellowreign
  • 3,528
  • 8
  • 43
  • 80
  • 5
    John Kloian's answer allows you to expire a single fragment. If you have a site that gets a fair amount of traffic and relies on caching, expiring everything could result in very slow page loads or timeout errors as the cache is warmed. – Patrick Brinich-Langlois Feb 25 '17 at 01:21
30

From the rails console:

Rails.cache.delete 'FRAGMENT-NAME'
John Kloian
  • 1,414
  • 15
  • 15
21

Here you are:

<% ActionController::Base.new.expire_fragment("foo_header_cache_#{@user.id}") %>

Reference:
- How to call expire_fragment from Rails Observer/Model?

Community
  • 1
  • 1
Adit Saxena
  • 1,617
  • 15
  • 25
12

From the console:

You can run this (ie. if you know the id is '1')

ActionController::Base.new.expire_fragment("foo_header_cache_1")

To use Rails.cache.delete you need to know the fragment name. In your case, it would be

Rails.cache.delete("views/foo_header_cache_1") # Just add 'views/' to the front of the string

If you have an array-based cache key using objects, such as:

cache([:foo_header_cache, @user])

Then you can get the fragment name like so

ActionController::Base.new.fragment_cache_key([:foo_header_cache, @user])

The name includes the id and updated_at time from any objects (to the yyyymmddhhmmss). It would be something like "views/foo_header_cache/users/1-20160901021000"

Or simply clear it using the array.

ActionController::Base.new.expire_fragment([:foo_header_cache, @user])
Mark Swardstrom
  • 17,217
  • 6
  • 62
  • 70
  • I think this is the most accurate answer. After many uses I figured this is a bit cleaner to use instead of calling the ActionController module: `Rails.cache.clear(['views', :foo_header_cache, @user])` (works in Rails 4.2 at least) – rorofromfrance Dec 22 '21 at 10:39