我在一个相当复杂的Rails应用程序中,独立使用模板继承和俄罗斯套娃缓存(使用cache_digests gem),并取得了很大的成功。
但是,我在尝试将这两种技术结合使用时遇到了困难,让我怀疑自己可能做错了什么...
举个极其简单的例子,考虑一个由两个控制器ThingOnes和ThingTwos组成的应用程序。该应用程序有一个布局(layouts/application.html.erb
),其中包含一个头文件:<%= render 'header' %>
。
默认情况下,Rails会在许多位置查找此局部视图,包括布局的视图目录(views/application/_header.html.erb
)以及当前控制器特定的视图(如views/thing_ones/_header.html.erb
或views/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原则,这是一个大问题。
因此,我的实际问题是...我是否做得正确?这似乎是一个相当重要的缺陷,会影响各种实现,但我找不到与此特定问题相关的讨论,所以我想知道其他人是否有更好的解决方法。是否有更好的方法来完成这个任务,或者至少自动指定整个模板依赖关系层次结构进行局部渲染?