HAML: RoR's new templating engine

I agree with everything Seth pointed out. Why not let any amount of
(non-newline) whitespace denote a new block, rather than only two
spaces?

I'd also like to add my voice to those who feel that adding support for
Ruby blocks would be a good idea. If you also added some character, say
'-', that denoted code that was executed but not used as output, then
you could do something like:

- for foo in @foolist
  %h1 foo.name
  %p foo.text

I echo this.

Have started using HAML for a major project, as it is simply beautiful.

However, I'm not going to write a partial for every tiny loop: it would
be madness.

Neither do I want to mess around with generating layout from a helper
object. Isn't that what views are for ?

Although I understand that 'code in views' == bad, surely the
equivalent of "take this collection of things (which were collected
together somewhere else) and show each one like this" is more markup
than code ?

I'm now in the curious position of using HAML for pretty much
everything, and calling in an rhtml partial when I need to pump out a
list. Hardly ideal...

Terry

Chris wrote:

Nex3 wrote:

I agree with everything Seth pointed out. Why not let any amount of
(non-newline) whitespace denote a new block, rather than only two
spaces?

I'd also like to add my voice to those who feel that adding support for
Ruby blocks would be a good idea. If you also added some character, say
'-', that denoted code that was executed but not used as output, then
you could do something like:

- for foo in @foolist
  %h1 foo.name
  %p foo.text

I'm not against using the - to mean "eval but don't print anything".
However, the problem is the way that its all parsed and executed. We
might be able to work something out, but the deal is that each line is
currently evaluated in-itself.

So this seems more like an implementation issue rather then there is no reason to allow it right? I really like your syntax but I think you will keep getting pushback until multi line iterations and if statements are allowed. I looked at the codebase and I don't think it would be too hard to add a little state to the parse loop to keep track of multi line statements and eval them accordingly.

I'm not sold on the idea that this is a good thing and the
implementation would become much more complex.

However, I still haven't seen any arguements on why this is a Good
Thing, beyond forces of habit, and that some rails helpers use it.
Tradition isn't a good arguement.

What about <% cache do %> blocks? what about content_for :sidebar blocks? there are really a ton of useful situations where the blocks in a view are very important.

Couldn't you do some look ahead when parsing the template? You already are loading all the lines into memory before processing with this line:

template.split(/\n/).map do |line|

What about preprocessing the template to combine multi line statements starting with == into one line statements starting with = and with the compressed lines separated with ;

so this:

%body
   #posts
     == @posts.each do |post|
     == link_to post.title, :action => 'foo', :id => post
     == end

becomes this internally after preprocessing before parsing:

%body
   #posts
     = @posts.each do |post| ; link_to post.title, :action => 'foo', :id => post ; end

Some stupid code that does this preprocessing:

       buffer = []
       seen = false
       last = false
       template.each_with_index do |line, index|
         if line.strip =~ /^==/
           unless seen
             buffer << line.sub(/==/,'=').chomp
             last = index
             seen = true
           else
             buffer[last] << ';'+line.sub('==', '').strip
           end
         else
           seen = false
           buffer << line
         end
       end

And then go into your normal parse loop now that the multi line statements are compressed to single line statements? I am sure there is a better way to do it but this seems feasible.

In the three fairly-complex projects I have done in HAML, besides
breaking habit, I haven't really *needed* blocks. The closest I got was
a pang of rememberance for how i'd do it in rhtml.

Maybe you haven't needed block because you weren't allowed to do them :wink: I think HAML is truly something very cool, I just think it won't get as much adoption as it should until you allow multi line statements period.

just my two cents here of course...

Cheers-
-Ezra

Chris wrote:

OK, i have > 30 controllers, with hundreds of views. Can you imagine all the work it would requrie to create sub-views for all my control loops!? I use rails to be speedy and efficient.

It's a pity HAML is doing this, otherwise it could be a massively used templating system.

I enjoyed Hampton's presentation at RailsConf yesterday, and I've just read through the whole of this thread.

One thing that strikes me is that Rails has an asymmetry between the use of files for helpers (where you can put many helpers in one file), and the use of files for partials (where you have have one file per partial). I get the impression that in Chris's case this would lead to an unmanageable mass of tiny files.

Would it be possible for HAML partials to get away from the "one file per partial" constraint? It would be good to be able to use named template fragments, defined either in the file that is using them or in a fragment library file looked up by convention (or explicitly imported).

In programming, it's a good idea to factor out a new method wherever you can put a meaningful name to a bunch of lines in an existing method. You wouldn't dream of doing this if every method had to live in its own file. Shouldn't the same principles apply to templates?

regards

   Justin Forder

In programming, it's a good idea to factor out a new method wherever you
can put a meaningful name to a bunch of lines in an existing method. You
wouldn't dream of doing this if every method had to live in its own
file. Shouldn't the same principles apply to templates?

Now _that_ is a smart thought !

Justin Forder wrote:

Would it be possible for HAML partials to get away from the "one file
per partial" constraint? It would be good to be able to use named
template fragments, defined either in the file that is using them or in
a fragment library file looked up by convention (or explicitly imported).

This idea needs further exploration... I like it. The concept reminds
me a bit of XSL templates: you would usually have many per file, but
HAML would of course have a different mechanism for including the
partials.

Here's an example XSL file if you've never seen one:
http://www.brics.dk/~amoeller/XML/xslt-4.1.html

John Philip Green

HI, does this new template engine code work well within Dreamweaver?
I have had very good success with RHTML code within DW.

Thanks,

-Conrad

I have been following this thread, though not too closely so I may have missed
some of the following points.

1. My first impression is HAML is so "leading edge" that current editors don't
have any support for it yet.

2. Although RHTML isn't "special" or "better" than ASP, JSP and the likes. However,
besides good compatibility, vanilla HTML do not need further processing. In HAML
just about every line needs to be transformed (HAML -> HTML or whatever). This
beg the question of performance. Are there performance issues we should be concerned
about?

3. HAML perhaps may be easily learned but I wonder how well this works in practice.
It is another layer of abstraction web designers/authors will need to deal with. I am not
sure how well HAML will be accepted in their world.

Long

Justin-

Now, *that's* along with my thinking.

Very soon we will indeed have multi-line statements. I'm going to make
it clear that I think 99% of the loops in views are *crap* and are
against HAML style.

However, I have wanted to be able to say this.

#links
  = link_to "signup", |
               :action => "go" |
               :id => @id |

I think this looks ok and works great for hashs and making stuff look
good by taking one line and making it go on multiple. That being said,
you could do a loop, though, I really don't recommend it most places.

Now, on to what you said! Your point that we need *another* solution
is exactly what I'm thinking about these days. The fact is that
ApplicationHelpers are weird things. They seem to be where you put it
when you don't have any other idea of where it should go.

DHH said something in his talk that really hit me. "When you fix one
thing, you notice how broken something else is!" That's exactly my
opinion. I think that haml's general restraints (Good Thing) just show
the awkwardness of Helpers at the moment. Or whatever it is that we
can think of that might be better.

One of the solutions I'm thinking of are Markaby fragments. I wish I
could have a backup file of markaby fragments that I can call and use
to describe the little bits that I'm now putting in helpers.

I think the views themselves are better now, now is time to turn our
attention towards new, totally crazy, rebellious ideas for helpers and
fragments.

Please email me directly with your thoughts.

hcatlin@gmail.com

Thanks,
Hampton.

I have been following this thread, though not too closely so I may have missed
some of the following points.

I'm happy to clarify them.

1. My first impression is HAML is so "leading edge" that current editors don't
have any support for it yet.

yes, wysiwyg editors have absolutely zero support. However, every
designer I know has dropped wysiwyg for a powerful toolkit of
in-browser css editors and etc.

I'd welcome someone to write that, but its not something any of the
designers I know using this require (or have asked for).

2. Although RHTML isn't "special" or "better" than ASP, JSP and the likes. However,
besides good compatibility, vanilla HTML do not need further processing. In HAML
just about every line needs to be transformed (HAML -> HTML or whatever). This
beg the question of performance. Are there performance issues we should be concerned
about?

It is slower. And you are right that it will always be a bit slower.
However, DBs remain the bottleneck in producing a page, not rendering.
While RHTML may be 2% of the render-time for a certain page, HAML is
about 3-4% of the time. That's absolutely acceptable in my mind when
DBs take up 85% and are still the actual slowdowns.

Caching isn't implemented yet, but it will be soon. (Patches welcome!)

3. HAML perhaps may be easily learned but I wonder how well this works in practice.
It is another layer of abstraction web designers/authors will need to deal with. I am not
sure how well HAML will be accepted in their world.

Every designer that I know that has used it "in the real world" won't
work without it now. They refuse to use anything else. *Not*
coder-designers, just designers.

HAML makes it much easier for a designer to parse in their mind what
is going on because of the syntax and etc. If statements, loops,
blocks, and hand-coded XHTML is probably the worst thing for a
designer to have to deal with. They should only care about
understanding the structure in the DOM.

We at unspace interactive have been using this successfully in all of
our projects over the past 3 months. It wasn't introduced after it was
created. We held it back to give it its paces and to see how it worked
out. There is a reason that we flew across the world to introduce it
at RailsConf Europe. Its because it works in a real-life situation and
produces great code with very little overhead.

Our goal is to deliver value to our clients, and HAML helps us accomplish that.

It works. Period.

-hampton.

PS: Though, we are always improving!!!!! It isn't finished yet. But,
now is the world's chance to make improvements and to make it kick
even more ass than we could do internally.

I'm going to have to agree on the designer issue. If your designer is using
DreamWeaver or some other WYSIWYG program, they won't like HAML. At least at
first. HAML is more like the underlying document structure. Not every design
requires knowledge of the document structure, but most good designs are
deliberate and are mindful of the document structure. If you design is not
in this category, rhtml still works fine.

One thing that would really help me (and I believe others) understand the
"it works" part of this equation is a non-trivial example of one action that
really does something interesting. Something that really exercises HAML so
we can learn by example.

This might include a form so we can understand why form_for blocks are not
as interesting in the context of HAML. Additionally, please consider Ezra's
comments about joining block statements because I know there are many
instances where I do things like:

<% content_for :sidebar %>
some arbitrary stuff, optionally drawn from instance variables
<% end %>

or even more frequently:

<% content_for :title %>

Thanks for opening this up to the rest of the Rails world.

Hampton wrote:

Speaking to the implementation issues of using loops, I've submitted a
patch that allows the following:
- for page in @pages
  %h1= page.name
  .page
    = page.text
- end
This works for all types of blocks. It should be possible to eliminate
the need to manually type "end" as well. So it's not a problem to
implement loops and blocks in HAML... it's just an issue of whether or
not we want them.

Personally, I feel that loops and especially if statements are
neccessary for the language. There are certainly many times when
they're inappropriate, but there are also many times when they're
legitimately useful. In addition, they're an integral part of Ruby;
various methods built into the language and into Rails rely upon
blocks, the ability to key off a boolean, and the like. HAML won't be
able to use any of this if it doesn't support blocks.

And the patch is ... where?

Nex3 wrote:

@s.ross: Here:
http://dev.hamptoncatlin.com/haml/ticket/16

I would add that one of the most Rails-esque things to do is just get
something working and then polish it up later. TDD encourages this too.
Here's an example from scaffold:

<% for column in Catalog.content_columns %>
<p>
  <%= column.human_name %>: <%=h @catalog.send(column.name) %>
</p>
<% end %>

<%= link_to 'Edit', :action => 'edit', :id => @catalog %> |
<%= link_to 'Back', :action => 'list' %>

Without knowing anything about the underlying model, this view uses loops to
iterate over the members of the content_columns collection twice. Yeah, the
problem can be solved other ways. It probably *will* be solved a different
way in the final implementation. But somethings just getting the CRUD to
work is enough to see whether you're headed in the right direction.

Would this be sooooo evil to include in HAML?

--steve

Joe Ruby MUDCRAP-CE wrote:

I feel like the suggestions for how to handle multi-line blocks here
are turning HAML into an ugly beast, should they come to fruition. It
seems to me that there are probably ways to figure out when a
multi-line statement terminates without any explicit help. For
starters, if = is encountered, but no special symbols for subsequent
lines, couldn't you assume the expression continues until the next
special symbol is encountered?

For what it's worth, I can tell you right now that I'd pretty much drop
HAML like a hot potato if it turned into something that required me to
do == or | for every line of a block. That seems very far off the mark
for what HAML promised out of the gates.

Don't worry, my patch deals with this. All you have to do for a block
is:

- block_magic do |param|
  = param.stuff
  %p= param.magic

No closing tag or repetitive characters needed.

I applied this patch and as I noted in Trac, it causes certain breakage in my
code. Maybe I did something wrong...

(eval):3:in `template_eval': compile error
(eval):3: parse error, unexpected '(', expecting $
$HAML_instance << ""( "fine" * 3).to_s << "\n"
                     ^
Extracted source (around line #0):

1: = "fine" * 3

Here's the template that breaks (expected result: finefinefine):

= "fine" * 3

And one that works around the above error:

%p= "fine" * 3

Nex3 wrote:

I am developing a Rails site and am gearing for deployment. The one last
bit I want to do (and need help with) is to make the site more professional
looking.

1. I need a good stylesheet color scheme for font, div borders and background.

2. I am somewhat a minimalist. I only need a handful of graphic icons and
maybe a site logo.

3. The overall site layout is done and set. I may need help with layout for
specific areas within a page.

Work will be off-site. I don't think it will require a lot of work (I could be
wrong) but if you are interested in helping, send me a note to

long755[@]rogers[dot]com.

In the message, describe your background and current work. Please include
links to live sites that you've designed or created graphics for. Note, resumes
will NOT be read.

I want to thank you all for your interest, but only successful candidates will
be contacted for round 2.

Cheers,

Long
PS: If you know of a good designer please forward this message.

Checking back in.. I lost steam with HAML. Going back to the few
templates I initially converted, I'm not sure I like it as much. I do
want to keep an eye on it, though.

Hampton, you commented on DBs being the bottleneck, not rendering, but
from what I've heard (including from members of Rails core), rendering
has actually been one of the most notorious performance monkeys on our
collective back for most of Rails life thus far.

This is just what I've heard, and I'd be interested for more of your
take on this.