5 ms·
Block Helpers in Rails 3
- extension 16y agoPerhaps 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 16y agoSure, 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 16y agoIndeed, 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 16y agoThe 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 16y agoWhat makes you think the author is unfamiliar with this?
- killbot5000 16y agoSince 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.
- sp4rki 16y agoWhy do you get that idea? I didn't get that impression at all. I don't think the author doesn't know the difference, I think he just used different terms to get his point across. I, thankfully, prefer to use Haml anyways :)
- lenary 16y agowell, thankfully lots of us use haml, not erb, so we don't care all that much