使用模板继承的俄罗斯套娃缓存存在问题

3

我在一个相当复杂的Rails应用程序中,独立使用模板继承和俄罗斯套娃缓存(使用cache_digests gem),并取得了很大的成功。

但是,我在尝试将这两种技术结合使用时遇到了困难,让我怀疑自己可能做错了什么...

举个极其简单的例子,考虑一个由两个控制器ThingOnes和ThingTwos组成的应用程序。该应用程序有一个布局(layouts/application.html.erb),其中包含一个头文件:<%= render 'header' %>

默认情况下,Rails会在许多位置查找此局部视图,包括布局的视图目录(views/application/_header.html.erb)以及当前控制器特定的视图(如views/thing_ones/_header.html.erbviews/thing_twos/_header.html.erb)。这意味着,为了缓存目的,我基本上有一个模板依赖列表(不包括引擎或其他任何内容),如下所示:

[
  "application/header",
  "thing_ones/header",
  "thing_twos/header"
]

现在,我们将渲染调用与缓存一起包装起来,如下所示:
<% cache 'header' do %>
  <%= render 'header' %>
<% end %>

很遗憾,运行rake cache_digests:nested_dependencies TEMPLATE=layouts/application会得到以下依赖列表。

[
  "layouts/header"
]

它似乎完全不关心模板继承。修改未包含在列表中的文件会如预期地影响未包含在列表中的文件——缓存未被正确地过期,显示陈旧的头部。
可以通过指定相关的模板路径来轻松解决这个问题,像这样:
<% cache 'header' do %>
  <%# Template Dependency: application/header %>
  <%# Template Dependency: thing_ones/header %>
  <%# Template Dependency: thing_twos/header %>
  <%= render 'header' %>
<% end %>

这似乎是一个非常糟糕的解决方案,因为它不易于扩展,并且需要大量无意义的修饰来缓存调用,以保留现有的模板继承行为。
同样地,可以更明确地指定头部位置,如下所示:
<% cache 'header' do %>
  <%= render 'application/header' %>
<% end %>

这也无法保留现有的模板继承行为,因此不适合我们的需求。
最后一个选项是将“cache”调用移动到头部局部文件中。这不仅效率低下,因为它使“render”调用不在缓存中。而且更加冗长(写两次一样的代码),不符合DRY原则,这是一个大问题。
因此,我的实际问题是...我是否做得正确?这似乎是一个相当重要的缺陷,会影响各种实现,但我找不到与此特定问题相关的讨论,所以我想知道其他人是否有更好的解决方法。是否有更好的方法来完成这个任务,或者至少自动指定整个模板依赖关系层次结构进行局部渲染?

我开始怀疑人们在部署过程中是否没有持久化这些缓存,或者其他什么原因... - Brad Werth
1个回答

1
问题实际上就是你在最后建议的:你需要将cache方法移动到你的渲染模板中。
这可能看起来像更多的代码,但这对于缓存摘要正常工作是必要的。此外,如果你的局部文件(_header.html.erb在应用程序中,thing_ones和thing_twos)不同,缓存键也应该不同。这意味着你最终应该得到像这样的东西:
# layouts/application.html.erb
<%= render 'header' %>

# application/_header.html.erb 
<% cache 'application_header' do %>
  ...
<% end %>

# thing_ones/_header.html.erb
<% cache 'thing_ones_header' do %>
  ...
<% end %>

# and thing_twos/_header.html.erb
<% cache 'thing_twos_header' do %>
  ...
<% end %>

如果没有不同的缓存键,这些缓存将会互相覆盖,也就是说,如果例如 application/_header.html.erb 先被缓存,那么它将在 ThingOnesThingTwos 页面中被渲染。请保留 HTML 标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接