Haml in SproutCore

Nerds never rest. Over the weekend I submitted a patch to add haml support to SproutCore with a few caveats. Almost immediately my new favorite aussie Lawrence Pit addressed those caveats and the patch was rolled into SproutCore 0.9.15. (A patch for sass was also submitted… is the addition of Red far behind?)

If you’re not coming from a Rails/Merb world haml likely slipped under your radar last year. Haml is a template language that aims to simplify the markup in your views by removing the need to type a bunch of meaningless extra characters, exporting very pretty, nicely indented output, and make it much easier to mix code and markup (which is the whole point of templates of course).

In haml (X)HTML tags are created with the % literal followed by the tag name. So %p and <p></p> are equivalent when run through haml’s parsing engine. That may not seem like much, but beyond trivial examples haml can be much nicer to look at. Compare the rhtml and haml versions of the imaginary code below:

  <strong class='<%= object.some_method%>' id='<%= object.class_name %>'><%= 'Hello, World!'.translate %></strong>

  %strong{:class => object.some_method, :id=> object.class_name }= 'Hello, World!'.translate

With rhtml you can end up with some massive visual clutter (%>'><%=' – which I believe is also ironically the japanese emoticon for “my cross eyed mutant monster from chibi vampire HATES ugly markup”) that Haml purposely avoids.

Haml is also highly intelligent and operates, like ruby, on the principle of least surprise. What happens, for example, if object.some_method returns nil? With rhtml you’ll end up with markup like:

  <strong class='' id='message'>Saluton al la tuta mondo!</strong>

An empty class isn’t the end of the world, but it sure is pointless. Haml will just ignore the entire class attribute when printing if it’s value in nil

  <strong id='message'>Saluton al la tuta mondo!</strong>

Many libraries will create helpers to deal with interweaving a lot of markup and code. SproutCore has it’s TagHelper module (which appears to be nabbed from Rails) that solves the problem like this:

  content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")

Using TagHelper your views end up as a mix of regular markup, markup interspersed with bits of <%= code %>, and areas where code is totally generating markup for you. The fact that we need additional code sitting on top of our template language to make it easier to use is a signal that our template language doesn’t really meet all our needs properly.

Other Niceties

In addition to making code betwixt markup less hideous, Haml also has some syntactic shortcuts for very common markup. If your classes and ids aren’t dynamic you don’t need to use a hash to set them. Haml borrows syntax from CSS and lets you use . (dot) and # (hash) to represent the two most common element attributes you’re likely to use.

  %strong#message_22.trasnlated.message= 'Hello, World!'.translate

  <strong id='message_22' class='trasnlated message'>Saluton al la tuta mondo!</strong>

If you’re using <div> for structural markup you can even leave off the %div part. Here’s adr-ish example:

  .adr
    .street-address= address.street
    .locality=       address.city
    .region=         address.state
    .postal-code=    address.zip

A SproutCore example

For a fully fleshed out example I converted the picker view from the SproutCore photos sample app to haml.
Drum roll please:
rhtml vs haml

Great! How do I use it?

Haml support is isn’t in the SproutCore gem just yet so if you’d like to experiment with Haml there’s a few things you’ll need to do. First, you’ll want to bone up on Haml a bit by going through the tutorial. When you’re feeling ready you can put the latest version of SproutCore in your application by updating to the latest gem with gem install sproutcore placing it in your applications /frameworks/sproutcore folder:

    cd /path/to/your/application
    cd frameworks
    git clone git://github.com/sproutit/sproutcore.git
  

Restart your SproutCore application and it should be using the local version of SproutCore in frameworks instead of the version included in the gem.

Inside your project’s lproj folder either convert an existing .rhtml file to haml format and change its extension to .haml or create a new .haml file. You won’t need to choose between rhtml and haml for a project; SproutCore will happily convert both appropriately to html and place them in your project.


About this entry