Tricky! I moved the module into ERB::Writeable.
Despite your super calls, I used Object.class_eval to dynamically override #puts, #print and #p at the start of ERB#result, and then undefs those methods at the end of #result. It's sure to be more of a performance hit (though I'll have to benchmark to see how much it affects things) but I wanted to really leave the house as clean when I left as when I entered.
Oh, I also needed to add some .to_s calls inside Writeable's methods, to handle non-string arguments.
In summary (for the google-able archives): using Mark's technique, I have made a patched version of ERB which causes calls to puts, print, and p inside an ERB to place their information into the ERB output string, instead of immediately sending the results to $stdout. (If you use this patch but need some debug information in your ERB template, you can still use $stdout.puts to hide output from the ERB string.)
You can download the patched file from http://phrogz.net/RubyLibs/erb_1.8.2_with_puts.rb.gz
After ungzipping, the file should be renamed to 'erb.rb' and replace the file in (for a standard install):
/usr/local/lib/ruby/1.8/erb.rb
Finally, for the naysayers (and the archive), this functionality (using Ruby code inside an ERB template to inject strings into the ERB template in place without using <%=...%>) can be achieved without the above patch by using the "eoutvar" option for ERB. By default, this is a local variable named "_erbout", but you can name it whatever you wish by modifying the fourth parameter to ERB.new. For example:
require 'erb'
template1 = <<'ENDTEMPLATE'
Hello
<% 1.upto(9){ |i|
_erbout << "\t#{i} x #{i} = #{i*i}"
_erbout << "\n" unless i==9
} %>
Goodbye
ENDTEMPLATE
ERB.new( template1 ).run
template2 = <<'ENDTEMPLATE'
Hello
<% 1.upto(9){ |i|
OUTPUT << "\t#{i} x #{i} = #{i*i}"
OUTPUT << "\n" unless i==9
} %>
Goodbye
ENDTEMPLATE
ERB.new( template2, nil, nil, 'OUTPUT' ).run
Both of the above output:
Hello
1 x 1 = 1
2 x 2 = 4
3 x 3 = 9
4 x 4 = 16
5 x 5 = 25
6 x 6 = 36
7 x 7 = 49
8 x 8 = 64
9 x 9 = 81
Goodbye
···
On Aug 19, 2005, at 2:07 AM, Mark Hubbart wrote:
How about this? Still somewhat hacky, but maybe less breakable. It
should work unless you supply a binding in the Kernel module context;
the new #puts is defined in Object.