我在Rails 4应用程序中有以下内容:
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
但缓存永远不会刷新。 此缓存显示最新添加的 5 个更新,但当我添加新更新时,它不会刷新缓存。
我已经验证了内存缓存正在运行。 这是在开发环境中,但我已为该环境打开缓存。
我在这里做错了什么?
问题是您在类方法和实例方法中使用self.class.name
。
首先,这是解决方案,self.cached_latest
更改为:
def self.cached_latest
Rails.cache.fetch([name, 'latest']) { Update.all.limit(5) }
end
在自点方法(类方法)中,您已经在class
中,因此调用self.class
将返回类的类,该类将是Class
的,而不是您期望的Update
(模型类的名称)
在实例方法flush_cache
对self.class.name
的调用正确返回Update
。因此,当您after_commit
时,它试图刷新['Update', 'latest']
缓存键,但您的self.cached_latest
类方法正在写入['Class', 'latest']
缓存键。
因此,问题在于您从两个不同的上下文调用self.class.name
,并且它返回了不同的值。
为了改进您的解决方案,您可以使用自破坏缓存键来取消after_commit
回调:
def self.cached_latest
Rails.cache.fetch([name, 'latest', count, order(updated_at: :desc).first.updated_at]) { Update.all.limit(5) }
end
此缓存键现在如下所示:
['Update', 'latest', 45, "date of latest record's updated_at timestamp"]
正如您现在可能知道的那样,一旦您创建或更新记录,向其添加expires
,您将拥有一个自我刷新缓存,此缓存键就会更改。