简短回答:当缓存键无效时缓存会更新。在您的情况下,当特定帖子的 updated_at 字段晚于缓存中的内容时,缓存将被更新。需要注意的是,缓存更新发生在第一次渲染视图中的新数据时,而不是在数据库中更新数据时。
详细回答:我强烈建议您阅读Caching with Rails 了解基础知识。
问题中发布的代码块使用Rails' Fragment Caching。 cache product 调用将生成一个缓存键,它是post.id、post.updated_at 和视图模板的 MD5 哈希的组合。 Rails 将在缓存中搜索该键,如果找到,将返回缓存值而无需渲染部分。这是缓存命中。如果没有找到缓存键,Rails 将渲染部分并将结果存储在缓存中以供将来使用。这是缓存未命中。
任何缓存方案的棘手部分是缓存验证,即确保缓存提供的数据有效且准确。例如,如果数据库中的数据发生了变化,我们希望提供数据库数据而不是陈旧(旧)的缓存数据。
Rails 通过构建上述缓存键“自动”解决了这个问题。如果post 记录中的数据发生变化,则post.updated_at 将被更新并使用新的缓存键,这将导致缓存未命中。当缓存中的数据旧时,这就是您想要发生的事情。同样,如果视图模板发生变化,那么视图的 MD5 哈希值也会发生变化,并且缓存键也会更新,从而导致缓存未命中。
如果shared/post_list 部分引用了post 记录中未捕获的数据或变量,这可能会成为问题。例如,如果部分更改取决于用户是否为管理员,那么您将希望在缓存键中捕获用户的管理员状态。你会做这样的事情:
<% cache [post, current_user.admin?] do %>
另一个常见的例子是,如果部分引用了与 post 相关的其他数据库对象。假设您的部分渲染了post.comments 的列表。如果评论更改,但该更改未触及post 记录的updated_at 字段,则缓存提供的数据将无效。通过将touch: true 添加到belongs_to 关联来解决此问题:
Class Comment < ActiveRecord:base
belongs_to :post, touch: true
...
end
上述代码将在其 cmets 之一发生更改时更新 post 记录的 updated_at。
最后,Rails 提供了一种叫做Collection Caching 的东西,这是一种更有效的渲染部分/模板集合的方法。您可以在示例中通过用一行代码替换整个 each 循环来实现这种形式的缓存:
<%= render partial: 'shared/post_list', collection: @posts, cached: true %>
缓存的内容比这里描述的要多得多。我建议您阅读这篇文章中链接的指南,以便您对缓存验证有一个透彻的了解。您可以通过缓存显着加快服务器速度。在某些情况下,我看到服务器响应时间下降了一个数量级。但是,除非您小心,否则您最终可能会在缓存中提供过时的日期。