RCR to modify #puts and #print inside ERB

Discussion in 'Ruby' started by Gavin Kistner, Sep 10, 2005.

  1. 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?)
    Gavin Kistner, Sep 10, 2005
    #1
    1. Advertising

  2. Hi --

    On Sat, 10 Sep 2005, Gavin Kistner wrote:

    > 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

    --
    David A. Black
    David A. Black, Sep 10, 2005
    #2
    1. Advertising

  3. 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.

    --
    Best regards, emailto: scholz at scriptolutions dot com
    Lothar Scholz http://www.ruby-ide.com
    CTO Scriptolutions Ruby, PHP, Python IDE 's
    Lothar Scholz, Sep 10, 2005
    #3
  4. On Sep 10, 2005, at 9:40 AM, David A. Black wrote:

    > Hi --
    >
    > On Sat, 10 Sep 2005, Gavin Kistner wrote:
    >
    >
    >> 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 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
    James Edward Gray II, Sep 10, 2005
    #4
  5. On Sep 10, 2005, at 8:40 AM, David A. Black wrote:
    > 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.

    --
    "When I am working on a problem I never think about beauty. I only
    think about how to solve the problem. But when I have finished, if
    the solution is not beautiful, I know it is wrong."
    - R. Buckminster Fuller
    Gavin Kistner, Sep 10, 2005
    #5
  6. On Sep 10, 2005, at 9:39 AM, James Edward Gray II wrote:
    > 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?
    Gavin Kistner, Sep 10, 2005
    #6
  7. Gavin Kistner wrote:

    > 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<%" or "%><%=some value%><%"?

    > 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
    Devin Mullins, Sep 10, 2005
    #7
  8. I would favor your RCR. I think no code will be broken because of the
    new behavior.

    Michel.

    On 9/10/05, Gavin Kistner <> wrote:
    > 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 )".)
    Michel Martens, Sep 10, 2005
    #8
  9. On Sep 10, 2005, at 12:53 PM, Devin Mullins wrote:
    >> 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<%" 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!")


    >> 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).


    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 :)
    Gavin Kistner, Sep 10, 2005
    #9
  10. Hi --

    On Sun, 11 Sep 2005, Gavin Kistner wrote:

    > On Sep 10, 2005, at 8:40 AM, David A. Black wrote:
    >> 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.


    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

    --
    David A. Black
    David A. Black, Sep 10, 2005
    #10
  11. Gavin Kistner wrote:

    > <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
    Devin Mullins, Sep 10, 2005
    #11
  12. Gavin Kistner

    Jay Levitt Guest

    In article <>,
    says...
    > 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 %>


    --
    Jay Levitt |
    Wellesley, MA | I feel calm. I feel ready. I can only
    Faster: jay at jay dot fm | conclude that's because I don't have a
    http://www.jay.fm | full grasp of the situation. - Mark Adler
    Jay Levitt, Sep 10, 2005
    #12
  13. On Sep 10, 2005, at 5:01 PM, Jay Levitt wrote:

    > 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
    James Edward Gray II, Sep 10, 2005
    #13
  14. Hi --

    On Sun, 11 Sep 2005, Jay Levitt wrote:

    > In article <>,
    > says...
    >> 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 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

    --
    David A. Black
    David A. Black, Sep 11, 2005
    #14
  15. Gavin Kistner

    Jay Levitt Guest

    In article <>,
    says...
    > 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?


    --
    Jay Levitt |
    Wellesley, MA | I feel calm. I feel ready. I can only
    Faster: jay at jay dot fm | conclude that's because I don't have a
    http://www.jay.fm | full grasp of the situation. - Mark Adler
    Jay Levitt, Sep 11, 2005
    #15
  16. Hi --

    On Sun, 11 Sep 2005, Jay Levitt wrote:

    > In article <>,
    > says...
    >> 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?


    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

    --
    David A. Black
    David A. Black, Sep 11, 2005
    #16
  17. Gavin Kistner

    Mark Hubbart Guest

    On 9/10/05, David A. Black <> wrote:
    > Hi --
    >=20
    > On Sun, 11 Sep 2005, Jay Levitt wrote:
    >=20
    > > In article <>,
    > > says...
    > >> 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 threa=

    d
    > > aren't active in the Rails group; Rails is where this sort of thing
    > > *really* would be nice.

    >=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)
    Mark Hubbart, Sep 11, 2005
    #17
  18. Hi --

    On Sun, 11 Sep 2005, Mark Hubbart wrote:

    > 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

    --
    David A. Black
    David A. Black, Sep 11, 2005
    #18
  19. Mark Hubbart wrote:

    >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*
    Devin Mullins, Sep 11, 2005
    #19
  20. Gavin Kistner

    Mark Hubbart Guest

    Hi,

    On 9/11/05, David A. Black <> wrote:
    > Hi --
    >=20
    > On Sun, 11 Sep 2005, Mark Hubbart wrote:
    >=20
    > > 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 stuf=

    f)
    > > #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"

    >=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
    > > 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.

    >=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.

    > > 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.

    >=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.

    > > 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?

    >=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
    Mark Hubbart, Sep 11, 2005
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steve V
    Replies:
    6
    Views:
    234
    Steve V
    Apr 20, 2005
  2. Gavin Kistner

    #puts inside ERB

    Gavin Kistner, Aug 18, 2005, in forum: Ruby
    Replies:
    5
    Views:
    248
    Gavin Kistner
    Aug 19, 2005
  3. Hal Fulton

    ERB and puts/print

    Hal Fulton, Sep 11, 2005, in forum: Ruby
    Replies:
    1
    Views:
    90
    Ara.T.Howard
    Sep 11, 2005
  4. Michael Brooks
    Replies:
    22
    Views:
    395
    Rick DeNatale
    Mar 27, 2007
  5. Raj Singh
    Replies:
    4
    Views:
    135
    Ryan Ingram
    Jan 29, 2008
Loading...

Share This Page