【问题标题】:Calling ERB recursively with binding results in lost output text使用绑定递归调用 ERB 会导致输出文本丢失
【发布时间】:2021-04-03 06:14:15
【问题描述】:

(注意:我使用的是 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 模板文件中指定的第一个“外部”字符串丢失了。 如果我们从 outer.erb 中的 ERB 调用中删除 binding

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

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

outer
inner

outer

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

【问题讨论】:

  • 这很奇怪。我可以验证这种行为,但我不明白缺少的outerbinding 的关系。这里没有什么是“绑定”的……没有变量在起作用,对吧?
  • 我认为问题在于 ERB 代码在构建它时将处理后的字符串存储在实例变量中,并且当包含 self 上下文和因此该实例变量的绑定被传递给ERB 再次构建一个内部字符串,该变量在开始之前被初始化为空字符串。因此需要指定不同的变量。

标签: ruby binding erb templating


【解决方案1】:

这可以通过使用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), 0, '-')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 2020-07-16
    • 2016-02-12
    • 1970-01-01
    相关资源
    最近更新 更多