You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 7片段缓存异常:修改links块触发所有缓存重写问题

问题原因分析

你遇到的核心问题是Rails默认会将模板的Digest值自动附加到所有片段缓存的键中:
当你修改users/index.html.erb里的links缓存块内容时,整个模板的Digest(日志中views/users/index:后面的哈希串)会更新。此时所有基于该模板的缓存键前缀都会变化,旧缓存键对应的片段无法被命中,Rails就会重新渲染所有缓存块并写入新的缓存键下,表现为未修改的缓存块也被"重新缓存"。

从你的日志能明显看到这个现象:每个缓存块都先执行Read fragment(读取旧Digest前缀的缓存,未命中),随后执行Write fragment(写入新Digest前缀的缓存)。

解决方案

方案1:跳过模板Digest(适用于完全独立的缓存块)

给每个cache调用添加skip_digest: true选项,让缓存键不再包含模板的Digest值,这样模板其他部分修改不会影响独立缓存块:

<% cache "users_filter", skip_digest: true do %>
  <%= render partial: "users/partials/filter"%>
<% end %>

<% @users.each do |user| %>
  <% cache user, skip_digest: true do %>
    <%= render user %>
  <% end %>
<% end %>

<% cache "links", skip_digest: true do %>
  <%= link_to "New user from here", new_user_path %>
  <%= link_to "Sign Out", destroy_member_session_path, data: { turbo_method: :delete} %>
<% end %>

方案2:绑定局部模板Digest(兼顾独立性和自动失效)

如果需要缓存块在自身局部模板修改时自动失效,可以将局部模板的Digest加入缓存键,同时跳过主模板的Digest:

<% cache ["users_filter", view_template_digest("users/partials/filter")], skip_digest: true do %>
  <%= render partial: "users/partials/filter"%>
<% end %>

<% @users.each do |user| %>
  <% cache [user, view_template_digest("users/user")], skip_digest: true do %>
    <%= render user %>
  <% end %>
<% end %>

这样只有当对应局部模板或用户对象本身变化时,缓存才会失效,主模板其他修改不会影响这些缓存块。

内容的提问来源于stack exchange,提问作者Muhammad Ans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 02:52:04