Ruby on rails Rails:如果存在缓存片段,则跳过控制器(使用cache_键)

Ruby on rails Rails:如果存在缓存片段,则跳过控制器(使用cache_键),ruby-on-rails,caching,Ruby On Rails,Caching,我已经使用缓存很长时间了,最近发现我的片段缓存并没有像往常一样阻止我的控制器执行代码。我已经把问题归结为与cache_键有关,这似乎是一个新特性 这是我以前的解决方案,不再按预期工作 产品#展示视图: cache('product-' + @product.id.to_s) do # View stuff end 产品#展示控制器: unless fragment_exist?('product-19834') # ID obviously dynamically loaded # Perf

我已经使用缓存很长时间了,最近发现我的片段缓存并没有像往常一样阻止我的控制器执行代码。我已经把问题归结为与cache_键有关,这似乎是一个新特性

这是我以前的解决方案,不再按预期工作

产品#展示视图:

cache('product-' + @product.id.to_s)  do
# View stuff
end
产品#展示控制器:

unless fragment_exist?('product-19834') # ID obviously dynamically loaded
# Perform slow calculations
end
缓存工作正常。它写入和读取片段,但它仍然执行控制器(这就是我想使用缓存的全部原因)。这归结为片段添加了唯一id,因此创建的片段类似于:

views/product-19834/b05c4ed1bdb428f73b2c73203769b40f
因此,当我检查片段_是否存在时,我没有检查正确的字符串(因为我检查的是'views/product-19834')。我还尝试使用:

fragment_exist?("product-#{@product.id}/#{@product.cache_key}")
但它使用与实际创建的缓存密钥不同的缓存密钥进行检查

我宁愿使用此解决方案,也不愿使用控制器缓存或类似于互锁的gems

我的问题是:
-如何在控制器中检查特定视图中是否存在考虑该缓存键的片段?

正如Kelseydh在链接中指出的那样,解决方法是在缓存请求中使用skip_digest=>true:

看法

控制器

fragment_exist?("product-#{@product.id}")

也许值得指出的是,虽然提议的解决方案(
fragment\u exist?
)可以工作,但它更像是一种黑客行为

在你的问题中,你说

它写入和读取片段,但仍执行控制器 (这就是我想使用缓存的全部原因)

因此,您真正想要的是控制器缓存“。但是片段缓存是“视图缓存”:

片段缓存允许将视图逻辑片段包装到 缓存块并从缓存存储区中取出 ()

对于“控制器缓存”,Rails已经提供了一些选项:


从我的观点来看,这些都更适合您的特定用例。

您使用过动作缓存吗?我以前尝试过,但结果证明不会在其他地方造成问题,我非常需要使用此解决方案。感觉不应该太过开箱即用,对吗?由cache_键附加的视图哈希字符串是视图模板的MD5哈希。不幸的是,这将很难从您的控制器访问。我建议重构控制器逻辑,以避免让耗时的逻辑依赖于现有视图片段缓存的结果。例如,您可以通过在控制器中缓存耗时的方法来解决这个问题。如果这是不可能的,那么一个快速的解决方法就是在生成缓存密钥时使用monkey patch rails停止添加MD5散列:谢谢,Kelseydh。该链接中的解决方案(skip_digest=>true)运行良好!如果你愿意的话,你可以把它作为一个答案。
fragment_exist?("product-#{@product.id}")