I have the following in a Rails 4 app:
class Update < ActiveRecord::Base
default_scope { order('created_at desc') }
after_commit :flush_cache
def flush_cache
Rails.cache.delete([self.class.name, 'latest'])
end
def self.cached_latest
Rails.cache.fetch([self.class.name, 'latest']) { Update.all.limit(5) }
end
end
But the cached is never flushed. This cache shows the latest 5 updates added, but when I add a new one, it's not flushing the cache.
I've verified memcached is running. This is in the development environment, but I have turned on caching for that environment.
What am I doing wrong here?
The problem is that you're using self.class.name
in a class method and an instance method.
First, here's the solution, change self.cached_latest
to:
def self.cached_latest
Rails.cache.fetch([name, 'latest']) { Update.all.limit(5) }
end
In a self dot method (a class method) you're already in the class
so calling self.class
will return the class' class which would be Class
and not Update
as you're expecting (the name of your model class)
In the instance method flush_cache
the call to self.class.name
was correctly returning Update
. So when you were after_commit
ing, it was trying to flush the ['Update', 'latest']
cache key but your self.cached_latest
class method was writing to the ['Class', 'latest']
cache key.
So, the problem was that you were calling self.class.name
from two different contexts and it was returning a different value.
To improve upon your solution you could do away with the after_commit
callback by using a self busting cache key:
def self.cached_latest
Rails.cache.fetch([name, 'latest', count, order(updated_at: :desc).first.updated_at]) { Update.all.limit(5) }
end
This cache key would now look something like:
['Update', 'latest', 45, "date of latest record's updated_at timestamp"]
As you might be able to tell by now, this cache key would change as soon as you create or update a record, add an expires
to it and you'll have a self flushing cache.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.