Haml Walkthrough: ERB

Now we’re going to walk you through the exact same process with which Haml was created. A well-formatted bit of HTML was changed step-by-step until Haml was born.

Let’s start with an example using ERB. It’s a pretty standard template you might find in any Ruby project. Don’t panic if you aren’t a Rubyist—it’s a straightforward example.

haml/haml_e1.html
 
<div​ id=”products”​>
 
<%- @products.each do |product| %>
 
<div​ class=”product” id=”product_<%= product.id %​>​”>
 
<div​ class=”name”​>​​<%= product.name %>​​</div>
 
<div​ class=”price”​>​​<%= product.price %>​​</div>
 
</div>
 
<% end %>
 
</div>

Executing this would print out each of the products in @products and assign each one a custom ID like product_23 (where the product’s ID is 23). It’s a very standard and well-formatted kind of template in ERB, and we are going to slowly convert this into Haml.

First off: it’s important to correctly indent ERB files, so there is no reason why you should have to spend so much time closing tags—it just seems wasteful. So, we’ll take the above example and remove all of the closing tags.

haml/haml_e2.html
 
<div​ id=”products”​>
 
<%- @products.each do |product| %>
 
<div​ class=”product” id=”product_<%= product.id %​>​”>
 
<div​ class=”name”​>​​<%= product.name %>
 
<div​ class=”price”​>​​<%= product.price %>

See how much cleaner it is? And notice that the <% end %> tag is gone too. Haml automatically figures out when to close a Ruby block. (This can vary in non-Ruby implementations.)

You’re probably thinking we’re secretly Python people because of the decision to make Haml “whitespace sensitive.” That term’s annoying. When looking at HTML, the advantages of getting rid of the closing tags were clear. Even when working in a language that doesn’t care about whitespace, most people still do. Having bad indentation is a serious issue in any bit of code or markup and should be treated as a flaw.

Haml used to accept only two spaces as indentation—no exceptions. That has since changed. Whatever you use to start indenting is what you must keep with. Just stay consistent. It can be a tab, or one space, or two tabs. It doesn’t matter. As long as it’s consistent, it’s OK.[20]

Moving on! We’re not nearly done yet.

Don’t you absolutely hate this line?

 
id=”product_<%= product.id %>”

Ruby has a fantastic built-in string interpolation feature that means you should be able to do product_#{product.id} and skip all that weirdness. So let’s do that.

haml/haml_e3.html
 
<div​ id=”products”​>
 
<%- @products.each do |product| %>
 
<div​ class=”product” id=”product_#{product.id}”​>
 
<div​ class=”name”​>​​<%= product.name %>
 
<div​ class=”price”​>​​<%= product.price %>

There’s only a small change this time, but already this example is far more readable. Always think about how readable something is at a glance. When you look at it, how quickly does your brain parse and understand what you’re seeing? Basically, this removes a bunch of unneeded symbols for your eyes to deal with.

It’s at this point that everyone’s dislike of % style tags comes to full vengeance. Has anyone else done PHP for too many years and been left scarred and angry? Let’s get rid of those!

haml/haml_e4.html
 
<div​ id=”products”​>
 
- @products.each do |product|
 
<div​ class=”product” id=”product_#{product.id}”​>
 
<div​ class=”name”​>
 
= product.name
 
<div​ class=”price”​>
 
= product.price

See, we kept the first character as - or = to signify nonprinting and printing lines. Anything after an = gets printed, and anything after a - is executed but its output ignored.

At this point in the transformation, printing lines have been moved down to their own line. We’ll actually rectify this later, but for now it makes parsing the document a lot easier. Besides, <div>= seems inelegant for some reason.

In order to get those back up on the other line, Haml tags must be different from static HTML tags. One of the design goals is that you can copy in some plain HTML (properly indented) and it won’t get too mad at you. Mostly this was a concern for the <meta> tags on a page, which no matter what you do are as ugly as sin.

So, let’s use the % character to mean <tag> and use the Ruby/JSON-style syntax for the attributes. (Note: The JSON-style syntax only works with Ruby versions 1.9+. In 1.8, you must use the hashrocket style of {“class” => “product”}.)

haml/haml_e5.html
 
%div{id: ”products”}
 
- @products.each do |product|
 
%div{class: ”product” id: ”product_#{product.id}”}
 
%div{class: ”name”}
 
= product.name
 
%div{class: ”price”}
 
= product.price

At this point, we have fully valid Haml. Congratulations! But we have a bit more to do. With this, we can now move those printing lines up again! It’ll look nice.

haml/haml_e6.html
 
%div{id: ”products”}
 
- @products.each do |product|
 
%div{class: ”product” id: ”product_#{product.id}”}
 
%div{class: ”name”}= product.name
 
%div{class: ”price”}= product.price

Now we are getting somewhere! But something is still not quite right. There is a lot of writing of class: and id:, and it requires the brain to read the letters to understand what it means. At this point, inspiration strikes. Can you think of a symbology that already exists for IDs and classes?

haml/haml_e7.html
 
%div#products
 
- @products.each do |product|
 
%div.product{id: ”product_#{product.id}”}
 
%div.name= product.name
 
%div.price= product.price

Bam! Using CSS-style naming! We already know what those symbols mean. We’re on a roll now!

In a larger example, there would be %div all over the place. And we still aren’t encouraging the use of classes and IDs. It’s a lot easier—a lot less typing to do the right thing.

What if we assumed that each tag was a <div> by default?

haml/haml_e8.html
 
#products
 
- @products.each do |product|
 
.product{id: ”product_#{product.id}”}
 
.name= product.name
 
.price= product.price

Now that’s nice! We only have to specify the name when it’s not a div. And if we’re lazy, it’s easier to name divs well than it is to type %div over and over again. This is precisely how Haml should encourage good behavior. With this shortcut, it’s actually hard to do the wrong thing and easier to do the right thing (i.e., name everything well!).

Now we’ve really arrived at some standard Haml. But there is one thing that is still troublesome—the whole id: ”product_#{product.id}” line. It is a bit of an ugly duckling there.

If your object has a good answer for the object.id call, then we can automatically figure out the ID and class name that the .product div should have. We take the object’s class and down-case it, add an underscore, then put in the obj.id value—all with this little shortcut.

haml/haml_e9.haml
 
#products
 
- @products.each do |product|
 
%div[product]
 
.name= product.name
 
.price= product.price

The product div will automatically receive the proper class and ID, as in our products example. When we say [product] though, we’re referring to the |product|variable. If we had named the variable in |product| as |x|, then it would be %div[x].

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset