使用绑定递归调用 ERB 会导致输出文本丢失

问题描述

(注意:我使用的是 Ruby 的 erb,而不是 Rails。)

当使用当前绑定从另一个 ERB 模板中解析一个 ERB 模板时,在调用内部模板之前的外部模板的文本会丢失。

例如:

inner.erb 文件内容

inner

outer.erb 文件内容

outer
<%= ERB.new(File.read('inner.erb')).result(binding) %>
outer

测试脚本erb-test(必须做chmod +x erb-test):

#!/usr/bin/env ruby

require 'erb'

puts ERB.new(File.read('outer.erb')).result

./erb-test输出是:

inner

outer

如图所示,outer.erb 模板文件中指定的第一个“外部”字符串丢失。 如果我们从 binding 中的 ERB 调用删除 outer.erb

<%= ERB.new(File.read('inner.erb')).result %>

...然后我们现在看到外部模板中指定的第一个 outer

outer
inner

outer

这是一个错误吗?你建议如何解决这个问题?我意识到最好限制模板可用的状态,通常我使用 ERB#result_with_hash 来做到这一点,但在子模板的情况下,即从另一个模板调用的模板,对我来说似乎合理内部模板继承了外部模板的绑定,因为它已经被限制了。

解决方法

这可以通过使用 eoutvar parameter to ERB.new 来解决,如下所示:

<%= ERB.new(File.read('inner.erb'),eoutvar: '@inner').result(binding) %>

ERB 源代码中的注释进一步解释了它:

# _eoutvar_ can be used to set the name of the variable ERB will build up
# its output in.  This is useful when you need to run multiple ERB
# templates through the same binding and/or when you want to control where
# output ends up.  Pass the name of the variable to be used inside a String.

outer.erb的内容改为:

outer
<%= ERB.new(File.read('inner.erb'),eoutvar: '@inner').result(binding) %>
outer

...结果是:

outer

inner

outer

请注意,如果您在构造函数调用中传递未命名参数,则需要改用命名方法,例如对于修剪模式:

    ERB.new(File.read(erb_filespec),eoutvar: eoutvar,trim_mode: '-')

代替:

    template = ERB.new(File.read(erb_filespec),'-')