Feature #11575
closedBlocks in ERB don't work as intended?
Description
I'm not sure if this is a problem with ERB, but here it goes -
require 'ERB'
require 'Erubis'
$results = []
def return_block(&block)
result = block.call
$results << result
return result
end
erb_template = <<-ERB
<% return_block { %>
<% "This should be stored in $results, but not sent to output" %>
<% } %>
<% return_block { %>
<%= "This should be stored in $results AND sent to output" %>
<% } %>
ERB
puts "Result of Template is:"
puts "---------------------"
#puts Erubis::Eruby.new(erb_template).result
puts ERB.new(erb_template).result(binding)
puts "---------------------"
puts "First call to return_block: #{$results[0]}"
puts "Second call to return_block: #{$results[1]}"
I'd expect the output to be
Result of Template is:
---------------------
This should be stored in $results AND sent to output
---------------------
First call to return_block: This should be stored in $results, but not sent to output
Second call to return_block:
This should be stored in $results AND sent to output
And this is exactly what I get when using Erubis
. When I use ERB
, the output I get is -
Result of Template is:
---------------------
This should be stored in $results AND sent to output
---------------------
First call to return_block:
This should be stored in $results AND sent to output
Second call to return_block:
This should be stored in $results AND sent to output
I'm checking this against older ruby versions too, will update with results.
Updated by rohitpaulk (Paul Kuruvilla) about 9 years ago
- Subject changed from ERB doesn't work as intended? to Blocks in ERB don't work as intended?
Updated by rohitpaulk (Paul Kuruvilla) about 9 years ago
Tried on 1.8.7, same results. Is there a spec for eRuby somewhere that I can refer to?
Updated by nobu (Nobuyoshi Nakada) about 9 years ago
- Status changed from Open to Third Party's Issue
ERB preserves white spaces even there is no <%= %>
tags.
Seems an Erubis's issue.
Updated by rohitpaulk (Paul Kuruvilla) about 9 years ago
I'm sorry I didn't make myself clear. Whitespace isn't the issue here - look at what's in $results
.
With Erubis:
First call to return_block:
This should be stored in $results, but not sent to output
Second call to return_block:
This should be stored in $results AND sent to output
With ERB:
First call to return_block:
This should be stored in $results AND sent to output
Second call to return_block:
This should be stored in $results AND sent to output
(I've stripped whitespace to make the issue obvious).
Updated by nagachika (Tomoyuki Chikanaga) about 9 years ago
- Status changed from Third Party's Issue to Assigned
- Assignee set to seki (Masatoshi Seki)
Hello, Rohit.
Thank you for your report.
I don't know it's a bug or s spec, but I've found that the $results[0] and $results[1] is the same object.
$results[0].object_id = $results[1].object_id # => return true at the last line of sample code.
seki-san, how do you think?
Updated by nagachika (Tomoyuki Chikanaga) about 9 years ago
Anyway, you can take a workaround to dup block value like result = block.call.dup
. Just for reference.
Updated by hsbt (Hiroshi SHIBATA) over 7 years ago
- Assignee changed from seki (Masatoshi Seki) to k0kubun (Takashi Kokubun)
- Target version set to 2.5
Updated by k0kubun (Takashi Kokubun) over 7 years ago
- Tracker changed from Bug to Feature
- Status changed from Assigned to Rejected
Whitespace isn't the issue here
That's wrong. Definitely whitespace matters. If you change to use a following template, you'll get an expected result and ERB and Erubis will work in the same way.
<% return_block { %><% "This should be stored in $results, but not sent to output" %><% } %>
<% return_block { %><%= "This should be stored in $results AND sent to output" %><% } %>
At least for me, this is not a bug but a feature request. I couldn't find any test that ensures the return value for the case that a part of template is captured by a block and it's called. You may be confused with ActionView's features available via yield.
And the original behavior you reported is caused by the fact that one String object is shared by all lines generated from ERB's "<%=". That's a very reasonable thing as both ERB and Erubis do.
It doesn't make sense to rely on the return value of internal code that touches temporal state of ERB. And a suggested template (embedding meaningless '<% "foo" %>') doesn't seem a reasonable real use case. As one of the ERB maintainers, I reject this proposal.