
Block Helpers in Rails 3 - jackowayed
http://timeless.judofyr.net/block-helpers-in-rails3
======
extension
Perhaps a better way to implement this would be to use Ruby's string
interpolation, which I'm pretty sure allows arbitrary expressions and
unlimited levels of nesting. For example, this ERB document:

    
    
      <html>
      <%= form_for @stuff do |f| %>
        <%= f.text_field :things %>
      <% end %>
      </html>
    

would be transformed into this Ruby:

    
    
      _buffer << "
      <html>
      #{ form_for @stuff do |f|
        _buffer << " #{ f.text_field :things } "
      end }
      </html>
      "
    

So, ERB goes back to being a very simple transformation with no special cases
and you can use any partial syntax in <%= %> blocks that would make sense.

EDIT: Ok, I'm pretty much giving up on this as I can't think of a good enough
solution. The two best options I came up with are:

1\. Feed the embedded code to Ripper as it comes in and use that to keep track
of the lexical context. Ripper is pretty fast so it might not be a significant
performance hit, but it only works in Ruby 1.9 and I don't know if a
comparable parser for 1.8 exists.

2\. Use a setter method like _buf= to append to the output buffer, and don't
wrap the embedded expressions in parens. Because the = operator has such low
precendence, the generated code will almost always behave as intended, but
there are a few lower precendence operators that will break like "and", "or",
and postfix "if", "unless", "while" and "until".

~~~
judofyr
Sure, any optimizing template engine _would_ use Ruby's string interpolation,
but it would still end up with this:

    
    
        _buffer << "<html>
        #{ form_for @stuff do |f| }
          #{ f.text_field :things }
        #{ end }
        </html>"
    

How are ERB going to figure out there's an opening of a block unless it
actually parses the expression? ERB only sees this:

    
    
        * "<html>"
        * Output: form_for @stuff do |f|
        * Output: f.text_field :things
        * Block:  end
        * "</html>"
    

Just a plain list, not a tree.

~~~
extension
Indeed, I'm hacking on it now and it seems like there is no way to avoid
detecting complete vs incomplete expressions. I guess the question then
becomes, can the expressions be classified in a way that is both fast and
correct? Let's see if I can find a way.

------
killbot5000
The author seems to be unfamiliar with the "expression" and "statement"
conventions used by imperative languages. An expression is something which has
a value, whereas a statement describes an action that doesn't (necessarily)
have a result. <%= %> expects an _expression_ ie something that has a value.
<% %> expects a _statement_ (or series of statements), which don't necessarily
have a value.

~~~
extension
What makes you think the author is unfamiliar with this?

~~~
killbot5000
Since the author admittedly made up the term "complete expression" whose
definition mirrors what I would expect for just "expression". He also used the
word "subexpression" to describe parts of something that would otherwise be
called a "statement".

Though I think his vocabulary is a little confusing, after re-reading I think
I get what he's actually complaining about. It is really awkward for a <%= %>
tag to not actually be a self-contained, parse-able expression. On the other
hand, you'd really rather have things like form_for _return_ the text to
print, not just print it (thus allowing the use of the <%= %> instead of <%
%>). It's just one of those annoying situations where attempting to be pure
and elegant results in an ugly kludge in the real world.

------
lenary
well, thankfully lots of us use haml, not erb, so we don't care all that much

