RCR to modify #puts and #print inside ERB

G

Gavin Kistner

Proposed RCR:

Modify ERB so that calls to #puts, #print, and #p inside the template
append the resulting string onto the local ERB output variable,
instead of sending the output to $stdout. #warn would still send to
STDERR (for debug messages seen but kept out of the result string)
and $stdout#<< could also be used.

Does anyone have any compelling reason why I should not make the
above RCR? I'll flesh it out as a proper RCR, citing the ruby-talk
threads with users wondering why it doesn't work as they expected.

As noted in another recent thread, I have in my possession an
implementation (perhaps not ideal) which accomplishes this already,
and would just need to be included. Would a C implementation also be
required for eruby, to keep feature parity between ERB and eruby?

(Should #p also be modified? Or is that logically a debug action
already?)
 
D

David A. Black

Hi --

Proposed RCR:

Modify ERB so that calls to #puts, #print, and #p inside the template append
the resulting string onto the local ERB output variable, instead of sending
the output to $stdout. #warn would still send to STDERR (for debug messages
seen but kept out of the result string) and $stdout#<< could also be used.

Does anyone have any compelling reason why I should not make the above RCR?
I'll flesh it out as a proper RCR, citing the ruby-talk threads with users
wondering why it doesn't work as they expected.

I can't think of any reason to do this other than the fact that people
who haven't learned how to use ERB expect it, and I don't consider
that a compelling reason. I would therefore not be in favor of it.
Further on the negative side, it would have the effect of collapsing
two very different logical levels into one. It just seems odd to have
three methods whose interpolated value is the value of an argument,
while everything else in the language is interpolated on the basis of
its actual value.


David
 
L

Lothar Scholz

Hello Gavin,

GK> Proposed RCR:

GK> Modify ERB so that calls to #puts, #print, and #p inside the template
GK> append the resulting string onto the local ERB output variable,
GK> instead of sending the output to $stdout. #warn would still send to
GK> STDERR (for debug messages seen but kept out of the result string)
GK> and $stdout#<< could also be used.

GK> Does anyone have any compelling reason why I should not make the
GK> above RCR? I'll flesh it out as a proper RCR, citing the ruby-talk

I will vote against this RCR.

I don't think it is good to change this. I'm quite sure you break
backward compatibility in a lot of places and i don't see any real need
to do this.

If you write a RCR please explain more detailed why you want to do
this and where you see compatibility problems, maybe you can convince
me to accept the RCR.

GK> and would just need to be included. Would a C implementation also be
GK> required for eruby, to keep feature parity between ERB and eruby?

If it is accepted, then yes, please.
There is already the "-%>" problem with eruby vs. ERB and its going to
piss off a lot of people.
 
J

James Edward Gray II

Hi --



I can't think of any reason to do this other than the fact that people
who haven't learned how to use ERB expect it, and I don't consider
that a compelling reason.

I have to agree. There's no advantage to having puts() work, since
you can just slap in the text itself with ERb tags as needed. I
personally think it's better that people confused by this aspect ask
here and get corrected, than it is to break puts() for them.

James Edward Gray II
 
G

Gavin Kistner

I can't think of any reason to do this other than the fact that people
who haven't learned how to use ERB expect it, and I don't consider
that a compelling reason.

Others have expressed similar sentiments, so I'm responding in general:

At work, our bug filing system has you rate each bug on several
different axes, one of which is "severity". One option is "Missing
functionality; workaround exists", and another (weightier) option is
"Missing functionality, no workaround". In general, having *a* way to
accomplish a task is not the same as having the 'ideal' way to
accomplish a task. It's better than nothing, but it's not perfect.

Separate from the "because it's what certain people expect" factor, I
consider the current method of appending strings to "_erbout" less
convenient/ideal than using muscle-memory-friendly methods like #puts.

To take it to the extreme, what if ERB did not support any Kernel
methods, but provided another mechanism for calling them? What if you
couldn't write "myobj.foo" but instead had to write "myobj.send
( :foo )" to invoke the method? The exact same functionality would
still be there...you would just need to remember, when using ERB, to
write your code in a different way than you do normally. My belief is
that it would be a PITA. The more the code you have to write inside
ERB blocks deviates from Ruby (syntax, idioms, or 'general use') the
less convenient it is to use. The more ERB 'just works' right out of
the box, the greater a tool it becomes to lure people to Ruby.

(I have coworkers who are considering using Ruby for code generation,
based on me showing how incredibly simple it was to use.)

Obviously (and thankfully) ERB is not at this far extreme, but it is
along this axis that I argue for including #puts and the like inside
ERB.

I understand the theoretical argument for backwards-compatibility.
Have you (dear reader) personally ever used #puts or #print inside an
ERB template for debugging output that you didn't want included in
the result? I know I haven't, but I accept that I'm a sample size of
one. If backwards compatibility is truly an issue (and this RCR were
accepted) then I suppose it would have to be something like an option
to the constructor. (But bleah, I really want it to just work,
without having to write "ERB.new( foo, nil, '%', nil, true )".)


If my above arguments do not sway the majority, then the feature
won't be added. I could just release some sort of "require
'erb_with_puts'" library that wraps around the existing ERB. No
worries. I'm just hoping to make Ruby better out of the box (IMHO)
for new-adopters and old alike.
 
G

Gavin Kistner

I personally think it's better that people confused by this aspect
ask here and get corrected, than it is to break puts() for them.

IMHO, they way it behaves currently is what is broken.

My personal mental model says that #puts is for outputting content
that is the desired output of your program (unlike #warn). An ERB
template is a parametrized program in its own right, and its output
is the resulting string. If you want debug output, use #warn.

That's how I look at it, anyhow. Do others actually think of an ERB
template as an enormous HEREDOC string in another file that is going
to be included in your program, and ERB as an uber-powerful gsub to
run on that string?
 
D

Devin Mullins

Gavin said:
Separate from the "because it's what certain people expect" factor, I
consider the current method of appending strings to "_erbout" less
convenient/ideal than using muscle-memory-friendly methods like #puts.

Can you give me an example of when appending to _erbout is necessary or
preferred rather than saying "%>some text said:
To take it to the extreme, what if ERB did not support any Kernel
methods, but provided another mechanism for calling them? What if you
couldn't write "myobj.foo" but instead had to write "myobj.send ( :foo
)" to invoke the method? The exact same functionality would still be
there...you would just need to remember, when using ERB, to write
your code in a different way than you do normally.

The exact same functionality *is* available when you puts or print. With
your change, people expecting to spit out debug messages would have to
do $stdout.puts...
The more ERB 'just works' right out of the box, the greater a tool it
becomes to lure people to Ruby.

Understood. Well, for what it's worth right now, the features it has
work almost exactly as they do in JSP, including the separation between
puts (System.out.println, as usual) and _erbout (newly conceived
out.println).
That's how I look at it, anyhow. Do others actually think of an ERB
template as an enormous HEREDOC string in another file that is going
to be included in your program, and ERB as an uber-powerful gsub to
run on that string?

Well, yes, but that's because I know how it works. I understand that
newbs don't see it that way. Those that know say, "Don't hide the truth!
Make the newbs learn!" You say, "Make the abstraction so pure that newbs
don't /need/ to learn!" There is some validity in that argument, but,
sadly, I'm going to side with Joel[1] on this one.

Devin
[1] http://www.joelonsoftware.com/articles/LeakyAbstractions.html
 
M

Michel Martens

I would favor your RCR. I think no code will be broken because of the
new behavior.

Michel.
 
G

Gavin Kistner

Can you give me an example of when appending to _erbout is
necessary or preferred rather than saying "%>some text<%" or "%><%
=some value%><%"?

It's never necessary, as %><%=foo%><% is equivalent to _erbout <<
foo.to_s
It's preferred (by me) in cases where control whitespace is
important, or where the typing of the above is far more cumbersome
than typing "puts foo"

Contrived Example 1:
<ul>
<% items.each do |item|
_erbout << "\t<li>#{item.value}</li>\n"
end
%></ul>

compared with
<ul>
<% items.each do |item|
<li><%=item.value%></li>
<% end
%></ul>

(Not only is the newline sort of annoying in the above, but "\t" is
clearly a single tab character, where indentation on your editor may
use spaces to precede the <li>)

Contrived Example 2:
<%
sum = 0
100.times do |i|
_erbout << i.to_s
sum += i
end
_erbout << (sum / 100).to_s
foo.bar()
%>

compared with:
<%
sum = 0
100.times do |i|
%><%=i%><%
sum += i
end
%><%=sum/100%><%
foo.bar()
%>

compared with:
<%
sum = 0
100.times do |i|
print i
sum += i
end
print sum / 100
foo.bar()
%>

The exact same functionality *is* available when you puts or print.
With your change, people expecting to spit out debug messages would
have to do $stdout.puts...

That's a good point. I suppose it seems 'correct' to me because (for
me) it's DWIM. As for for debug messages, I argue that debug messages
should be done with #warn anyhow (which would remain unchanged) as
STDERR is more appropriate (I think) than STDOUT. And, I simply
didn't believe that anyone was actually using the puts-in-erb-for-
debug functionality. (And I suppose I still won't, until someone says
"Yes, I use that!")

Understood. Well, for what it's worth right now, the features it
has work almost exactly as they do in JSP, including the separation
between puts (System.out.println, as usual) and _erbout (newly
conceived out.println).

So it currently meshes well for people coming from JSP, eh? That's
good to know.

Well, yes, but that's because I know how it works. I understand
that newbs don't see it that way. Those that know say, "Don't hide
the truth! Make the newbs learn!" You say, "Make the abstraction so
pure that newbs don't /need/ to learn!" There is some validity in
that argument, but, sadly, I'm going to side with Joel[1] on this one.

Devin
[1] http://www.joelonsoftware.com/articles/LeakyAbstractions.html

Thanks for the article. I love reading Joel :)
 
D

David A. Black

Hi --

Others have expressed similar sentiments, so I'm responding in general:

At work, our bug filing system has you rate each bug on several different
axes, one of which is "severity". One option is "Missing functionality;
workaround exists", and another (weightier) option is "Missing functionality,
no workaround". In general, having *a* way to accomplish a task is not the
same as having the 'ideal' way to accomplish a task. It's better than
nothing, but it's not perfect.

Separate from the "because it's what certain people expect" factor, I
consider the current method of appending strings to "_erbout" less
convenient/ideal than using muscle-memory-friendly methods like #puts.

To take it to the extreme, what if ERB did not support any Kernel methods,
but provided another mechanism for calling them? What if you couldn't write
"myobj.foo" but instead had to write "myobj.send( :foo )" to invoke the
method? The exact same functionality would still be there...you would just
need to remember, when using ERB, to write your code in a different way than
you do normally.

But code isn't normally inserted into a text template. It's a
specialized situation. There's no way, and no reason, to sweep that
under the carpet.
My belief is that it would be a PITA. The more the code you
have to write inside ERB blocks deviates from Ruby (syntax, idioms, or
'general use') the less convenient it is to use. The more ERB 'just works'
right out of the box, the greater a tool it becomes to lure people to Ruby.

I admit I am very down on luring people to Ruby by introducing
inconsistencies and anomalies into the language and libraries. What
this particular special case would do would be to mask the fact that
puts and print are method calls with return values. That creates the
need to explain one or both of two things: the fact that, elsewhere,
they do behave like normal methods, and the fact that, in ERB, they
don't. It's a double twist in the road; so why not just learn how it
really works in the first place?

In the short term, having the puts/print exception might allow a few
people to indulge habits that correspond to a novice's first
instincts. But in the long term, what makes Ruby simple and
attractive, in my view, is in part the fact that while there *are*
advanced features and techniques, those features and techniques tend
to be built up incrementally and transparently from the simple things.
I would rather see people invest effort in really understanding method
calls and return values, than have to learn ad hoc how particular
method calls operate in different contexts. It's sort of like having
to learn irregular verbs.


David
 
D

Devin Mullins

Gavin said:
<Contrived Example 1 & Contrived Example 2>

Thanks. #1 seems like a good example. #2 seems a little too contrived -
your example obviously doesn't need erb - and I would imagine that the
addition of markup would make the erb syntax a little less ugly. That
said, I don't feel like trying to make a counter-example, so take that
with a grain of salt.
That's a good point. I suppose it seems 'correct' to me because (for
me) it's DWIM. As for for debug messages, I argue that debug messages
should be done with #warn anyhow (which would remain unchanged) as
STDERR is more appropriate (I think) than STDOUT. And, I simply
didn't believe that anyone was actually using the puts-in-erb-for-
debug functionality. (And I suppose I still won't, until someone says
"Yes, I use that!")

I should mention, I don't really use erb, so I'd abstain from the vote.
I just piped up to provide a little analysis. I'm starting a Rails
project (finally), so maybe I'll have some better opinions in a couple
weeks. :)
So it currently meshes well for people coming from JSP, eh? That's
good to know.

Yeah. (Well, % at the beginning of a line is new.) I don't know what
that's worth, though. All the Manly Men of the Java web world would
never run into the problem, because 1. they wouldn't place logging code
inside JSP (ideally no logic at all, using custom tags where logic would
be needed), 2. they'd be using log4j, and 3. they'd never use
out.println, if only for the sake of purity.
Thanks for the article. I love reading Joel :)

<homer>Mmm... controversy...</homer>

Devin
 
J

Jay Levitt

My personal mental model says that #puts is for outputting content
that is the desired output of your program (unlike #warn). An ERB
template is a parametrized program in its own right, and its output
is the resulting string. If you want debug output, use #warn.

Agreed. I find it interesting that most of the responders to the thread
aren't active in the Rails group; Rails is where this sort of thing
*really* would be nice.

I admit I used "puts-as-debug" the other day, but only because I was
doing a quick-and-dirty test and it was the first way I figured out to
get some Rails output into webrick. It's certainly not something I'd
keep in the code for more than 10 minutes.

And in Rails, where ERB owns the view, Gavin's examples don't strike me
as controlled at all - you often end up jumping between ERB and HTML
tags. Here's some code from the Agile Rails book that could look a lot
nicer if the "puts" metaphor were available:

<% for product in @products -%>
<h3><%= h(product.title) %></h3>
<%= product.description %>
<span class="catalogprice"><%= fmt_dollars(product.price) %>
</span>
<% end %>

vs.

<% for product in @products
puts "<h3>", h(product.title), "</h3>",
product.description,
'<span class="catalogprice">', fmt_dollars(product.price),
"</span>"
end %>
 
J

James Edward Gray II

Here's some code from the Agile Rails book that could look a lot
nicer if the "puts" metaphor were available:

<% for product in @products -%>
<h3><%= h(product.title) %></h3>
<%= product.description %>
<span class="catalogprice"><%= fmt_dollars(product.price) %>
</span>
<% end %>

vs.

<% for product in @products
puts "<h3>", h(product.title), "</h3>",
product.description,
'<span class="catalogprice">', fmt_dollars(product.price),
"</span>"
end %>

Have you considered using Rails's programatic Builder views?

James Edward Gray II
 
D

David A. Black

Hi --

Agreed. I find it interesting that most of the responders to the thread
aren't active in the Rails group; Rails is where this sort of thing
*really* would be nice.

I love Rails and I use it quite a lot. But I like ERB to behave
in the consistent, non-special-cased way it now does, which is
perfectly straightforward given how method calls work in Ruby (which
is a matter of public record :) I also don't like the idea of
changing things around in the language because the changes would suit
a given application, project, or framework (though in this case, for
me, that's a moot point because I don't think it would be suitable
anyway).


David
 
J

Jay Levitt

I like ERB to behave
in the consistent, non-special-cased way it now does, which is
perfectly straightforward given how method calls work in Ruby (which
is a matter of public record :) I also don't like the idea of
changing things around in the language because the changes would suit
a given application, project, or framework

Then maybe the answer would be for ActionPack to override the behavior
of puts while parsing a view..? That might make everyone happy, ya?
 
D

David A. Black

Hi --

Then maybe the answer would be for ActionPack to override the behavior
of puts while parsing a view..? That might make everyone happy, ya?

I think you're making too much of this perceived separation between
people who don't like the magic puts/print idea, and people who use
Rails. I am living proof that there is no such separation :) My
dislike of the magic puts/print applies to its use in ActionPack
templates as much as anywhere else. I just don't think it's a good
idea to single these methods out for anomalous behavior in templates.


David
 
M

Mark Hubbart

Hi --
=20
On Sun, 11 Sep 2005, Jay Levitt wrote:
=20
=20
I love Rails and I use it quite a lot. But I like ERB to behave
in the consistent, non-special-cased way it now does, which is
perfectly straightforward given how method calls work in Ruby (which
is a matter of public record :) I also don't like the idea of
changing things around in the language because the changes would suit
a given application, project, or framework (though in this case, for
me, that's a moot point because I don't think it would be suitable
anyway).

I'm getting the idea that the people on each side of this discussion
disagree because they have different mental models of what ERB does,
and what a ERB document is:

1. ERB just implements very fancy, flexible, string interpolation.
or
2. ERB documents are executable code (actual programs), where text
prints itself, and code blocks get run.

#1 is, I gather, much like the JSP way (though I've never done JSP stuff)
#2 is much like PHP.

If you are in the #1 camp, I suspect you think this RCR would not be
all that much different from one allowing this:
"#{puts 23}" #=3D=3D> "23\n"

If you are in camp #2, you probably just wonder why stuff you output
via #print or #puts doesn't end up with the rest of your ERB program's
output.

I'm in camp #2; I came to Ruby from PHP, and think of the template as
an actual program, an executable script with controlling statements
(Ruby code) embedded in self-printing text. I was shocked and greatly
disappointed when I found out that puts didn't work (yes, I thought it
was *broken*). I delved deeper and discovered that it was simply due
to an implementation issue; I assumed no one had fixed it because it
was too complicated a fix.

Now, I have a proposal: What if _erbout was made into a StringIO, and
we shifted the idea from an ERB template to an ERB program? Then would
it make sense for puts to output to _erbout?

cheers,
Mark

(my apologies if any part of this doesn't make sense, it's been a very long=
day)
 
D

David A. Black

Hi --

I'm getting the idea that the people on each side of this discussion
disagree because they have different mental models of what ERB does,
and what a ERB document is:

1. ERB just implements very fancy, flexible, string interpolation.
or
2. ERB documents are executable code (actual programs), where text
prints itself, and code blocks get run.

#1 is, I gather, much like the JSP way (though I've never done JSP stuff)
#2 is much like PHP.

If you are in the #1 camp, I suspect you think this RCR would not be
all that much different from one allowing this:
"#{puts 23}" #==> "23\n"

Yes, that captures the problem exactly. #{} executes what's in side
it and interpolates the value as a string, and having it do otherwise
based on the name of the method would be anomalous and awkward.
If you are in camp #2, you probably just wonder why stuff you output
via #print or #puts doesn't end up with the rest of your ERB program's
output.

If you want puts and print to behave anomalously, that's OK. But
there's no mystery to why they don't. They behave exactly the same
way every other method behaves. I don't think the *absence* of a
"magic" or special case should be a source of wonder :)
I'm in camp #2; I came to Ruby from PHP, and think of the template as
an actual program, an executable script with controlling statements
(Ruby code) embedded in self-printing text. I was shocked and
greatly disappointed when I found out that puts didn't work (yes, I
thought it was *broken*). I delved deeper and discovered that it was
simply due to an implementation issue; I assumed no one had fixed it
because it was too complicated a fix.

The "coming from PHP" argument, I fear, is illogical. It predicates
that whoever designed templating in PHP was empowered to make
decisions for authors of future templating systems -- and by
extension, presumably, everything else about future programming
languages. That, in turn, would mean that there could be no further
languages after PHP.

In fact, there could only be one language at all, because the people
who learned the first language would "come from" that language and
therefore be constrained to do things as they were done in that
language.

I know you're not really suggesting that Ruby become PHP. But the
"coming from" thing, while interesting in terms of our various
biographies, has nothing to do with Ruby per se, and has no persuasive
weight when it comes to discussing possible changes to Ruby. How
could it? How could Ruby do everything everyone did in the last
language they used? And *why* should Ruby play that kind of
self-effacing, chameleon-like role? Why doesn't Ruby get to be Ruby,
like PHP gets to be PHP?

My advice is that you break the cycle: come from PHP when you're using
PHP, and come from Ruby when you're using Ruby. It makes things more
harmonious. It's also much more fair to Ruby: instead of viewing Ruby
as "broken" because it doesn't do X like PHP, Y like C++, or Z like
Perl, you get to explore and understand Ruby on its own terms.

That doesn't mean you never think anything in Ruby should be changed.
(It doesn't even mean that puts and print shouldn't be made to behave
in a bizarre manner in ERB :) It's just an acknowledgement of the
fact that there's a design to Ruby, and of the fact that it is not
incumbent on Ruby to play the role of a language-idiom sponge.
Now, I have a proposal: What if _erbout was made into a StringIO, and
we shifted the idea from an ERB template to an ERB program? Then would
it make sense for puts to output to _erbout?

Yes, you should be able to do: $stdout = _erbout and have stuff go
to that stream if _erbout is a StringIO object.

I'm not sure about the template/program distinction. If you've got:

Hello, my name is <%= name %>.

and call that a "program", to me it implies that "Hello, my name is"
is part of a programming language. Also I don't think redirecting
$stdout causes a template not to be a template. But I may be looking
at it wrongly (and it's more or less "academic", as they say :)


David
 
D

Devin Mullins

Mark said:
I'm getting the idea that the people on each side of this discussion
disagree because they have different mental models of what ERB does,
and what a ERB document is:

1. ERB just implements very fancy, flexible, string interpolation.
or
2. ERB documents are executable code (actual programs), where text
prints itself, and code blocks get run.

#1 is, I gather, much like the JSP way (though I've never done JSP stuff)
Observant. The JSP way (which is also the Rails way) embraces MVC, and
avoids sticking domain logic in the template. The kind of code that sits
in a Rails view is "for foo in barlist" and "link_to :action =>
'someaction'". (In truth, the design of the JSP spec didn't really have
this in mind; rather, it flowed out through a couple years in the "real
world" as the most natural usage of JSP.)
#2 is much like PHP.

If you are in the #1 camp, I suspect you think this RCR would not be
all that much different from one allowing this:
"#{puts 23}" #==> "23\n"
It really is about inconsistency in behavior. Java falls prey to
inconsistent behavior for the sake of making some particular special
case "so easy you don't have to think about it." For me, Ruby was sort
of a safe haven from that.
Now, I have a proposal: What if _erbout was made into a StringIO, and
we shifted the idea from an ERB template to an ERB program? Then would
it make sense for puts to output to _erbout?
That's not an altogether horrible idea. Changing mindsets about ERB
turns it into one big embedded interpreter (capturing output the same
way that Kernel#` does) rather than one big string interpolation. I
would then be more likely to want *every* form of standard output to get
captured, then -- whether from puts, print, p, $stdout.write, log4r, ...
and I don't really want that. :/

I have a proposal, too. What if ERB exposed (and documented) eputs,
eprint, and ep methods to the templates? I would be coo wit dat.
(my apologies if any part of this doesn't make sense, it's been a very long day)
Nope, all very sensical.

Devin
oops! my opinion's showing. *zip*
 
M

Mark Hubbart

Hi,

Hi --
=20
On Sun, 11 Sep 2005, Mark Hubbart wrote:
=20
=20
Yes, that captures the problem exactly. #{} executes what's in side
it and interpolates the value as a string, and having it do otherwise
based on the name of the method would be anomalous and awkward.
=20
=20
If you want puts and print to behave anomalously, that's OK. But
there's no mystery to why they don't. They behave exactly the same
way every other method behaves. I don't think the *absence* of a
"magic" or special case should be a source of wonder :)

That's the thing; to those of us who don't see it as just "fancy
string interpolation", the *current* behavior is anomalous, not the
suggested behavior. The current behavior actually seems rather magic,
until you discover why it behaves that way, after which it just feels
poorly implemented.
=20
The "coming from PHP" argument, I fear, is illogical. It predicates
that whoever designed templating in PHP was empowered to make
decisions for authors of future templating systems -- and by
extension, presumably, everything else about future programming
languages. That, in turn, would mean that there could be no further
languages after PHP.
=20
In fact, there could only be one language at all, because the people
who learned the first language would "come from" that language and
therefore be constrained to do things as they were done in that
language.
=20
I know you're not really suggesting that Ruby become PHP. But the
"coming from" thing, while interesting in terms of our various
biographies, has nothing to do with Ruby per se, and has no persuasive
weight when it comes to discussing possible changes to Ruby. How
could it? How could Ruby do everything everyone did in the last
language they used? And *why* should Ruby play that kind of
self-effacing, chameleon-like role? Why doesn't Ruby get to be Ruby,
like PHP gets to be PHP?
=20
My advice is that you break the cycle: come from PHP when you're using
PHP, and come from Ruby when you're using Ruby. It makes things more
harmonious. It's also much more fair to Ruby: instead of viewing Ruby
as "broken" because it doesn't do X like PHP, Y like C++, or Z like
Perl, you get to explore and understand Ruby on its own terms.
=20
That doesn't mean you never think anything in Ruby should be changed.
(It doesn't even mean that puts and print shouldn't be made to behave
in a bizarre manner in ERB :) It's just an acknowledgement of the
fact that there's a design to Ruby, and of the fact that it is not
incumbent on Ruby to play the role of a language-idiom sponge.

I provided the "coming from PHP" simply for context. I know that
"language X does it this way" is not a final argument for making Ruby
do things a certain way.

However, if the (arguably) definitive templating language has a
certain major concept built in, then it could merit a look if you are
building a system that is basically the same.
=20
Yes, you should be able to do: $stdout =3D _erbout and have stuff go
to that stream if _erbout is a StringIO object.
=20
I'm not sure about the template/program distinction. If you've got:
=20
Hello, my name is <%=3D name %>.
=20
and call that a "program", to me it implies that "Hello, my name is"
is part of a programming language. Also I don't think redirecting
$stdout causes a template not to be a template. But I may be looking
at it wrongly (and it's more or less "academic", as they say :)

I think I may have explained myself poorly last night. (it was after
3, after all!) I'll give one more try.

In PHP, pages are being streamed from the server to the client. At the
beginning of a PHP document, you are in streaming text mode; all the
characters are printed to the output stream until the sequence "<?" is
reached. Then, everything is considered code up until the closing
bracket. Any print/echo statements are printed directly to the output
stream, in sync with the surrounding text. In fact, the "<?=3Dfoo?>"
type construction that some here are saying should be used instead of
print/puts is considered a shorthand replacement for "<? echo foo ?>",
and isn't even available unless short tags are turned on.

So that's the PHP background that I was referring to. Now the StringIO idea=
...=20

A simple ERB template that looks like this:
---
<% who =3D "world" %>
Hello, <%=3Dwho%>!
---

Gets translated into code something like this:
---
_erbout =3D ""
who =3D "world"
_erbout.concat "Hello, "
_erbout.concat who.to_s
_erbout.concat "!"
_erbout
---

Using the streaming output idea, this could be expected to look more like t=
his:

---
who =3D "world"
print "Hello, "
print who.to_s
print "!"
---

One could capture the output by setting the default output to a
StringIO; this is similar to what I did in a previous solution. It is
rather easy to put together a simple, thread-safe version that does
this. Currently, the default is to capture the output as a string, but
a webserver-related use would probably just send the output directly
to the browser *as it is being output*, rather than building the
string and sending it all at once.

I don't see this as being about adding "magic" to the implementation.
If you are of the mindset that the template is concatting to a string,
the puts idea doesn't make sense; but if you see it as printing to an
output stream (with the whole _erbout thing just being an
implementation issue), then the lack of a working print/puts is what
doesn't make sense.

cheers,
Mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top