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
相关产品推荐
相关产品推荐

