为什么erb块连接块内容

时间:2019-06-27 14:54:22

标签: ruby-on-rails ruby erb

我有以下代码:

require 'erb'

def body &block
  content = block.call
  content = block.call
  content = block.call
  content
end

x = 2
template = ERB.new <<-EOF
  <% body do %>
     2
  <% end %>
EOF

template.run(binding)

执行时,它输出2 2 2。为什么在block.call方法内对body的每次调用中,它都是将块的内容串联在一起?

为什么如果我使用以下模板,它不会发生:

template = ERB.new <<-EOF
  <%= body do
     2
  end %>
EOF

我无法确定这里发生的事情。我在rails上遇到了这个问题,但是将代码隔离到普通的Ruby中,试图了解问题所在。

1 个答案:

答案 0 :(得分:3)

这是因为ERB的工作原理。有关旧模板,请参见由erb生成的红宝石源(以下为template.src进行了美化):

_erbout = +''
_erbout.<< "  ".freeze
body do
  _erbout.<< "\n     2\n  ".freeze      # <<-- this is the line that produces extra output
end
_erbout.<< "\n".freeze
_erbout

,对于后者:

_erbout = +''
_erbout.<< "  ".freeze
_erbout.<<(( body do
     2                                  # <<- and this time it is just plain ruby code
  end
).to_s)
_erbout.<< "\n".freeze
_erbout

请注意运行时块如何输出到同一缓冲区。

实际上,这是正常现象并且已被广泛使用,例如,对于传递给each方法的以下代码块,您希望每次运行的输出都可以串联:

<% @items.each do |item| %>
  Item <%= item %>
<% end %>