Почему блоки erb объединяют содержимое блока - PullRequest
1 голос
/ 27 июня 2019

У меня есть следующий код:

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 Ответ

3 голосов
/ 27 июня 2019

Это потому, что работает ERB. Смотрите сгенерированный в erb источник ruby ​​для ваших шаблонов (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 %>
...