Reputation: 1258
I have the following code:
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)
When I execute it outputs 2 2 2
. Why in each call to block.call
inside the body
method it is concatenating the content of the block?
Why if I use the following template it doesn't happens:
template = ERB.new <<-EOF
<%= body do
2
end %>
EOF
I can't get my mind around what's happening here. I had this problem with rails but isolated the code to plain Ruby to try to understand what the problem was.
Upvotes: 1
Views: 361
Reputation: 18474
This is because how ERB works. See erb-generated ruby source for your templates (template.src
, below is prettified), for the former template:
_erbout = +''
_erbout.<< " ".freeze
body do
_erbout.<< "\n 2\n ".freeze # <<-- this is the line that produces extra output
end
_erbout.<< "\n".freeze
_erbout
and for the latter:
_erbout = +''
_erbout.<< " ".freeze
_erbout.<<(( body do
2 # <<- and this time it is just plain ruby code
end
).to_s)
_erbout.<< "\n".freeze
_erbout
note how blocks output to the same buffer when being run.
Actually this is normal and is widely used, for example for the below block that's passed to each
method you expect output from each run to be concatenated:
<% @items.each do |item| %>
Item <%= item %>
<% end %>
Upvotes: 3