We build Web & Mobile Applications.

< All Articles

Markaby tips

One of the good things about the high level of activity in the Rails world is that very often if you don’t like the default way of doing things there are usually several alternatives. A good example is the choice of templating language: if you don’t like ERb (and I don’t as it smells too much like PHP) then you can use something else. I’m personally a HAML fan but the project I’m currently working on - adding new features to an existing site that was developed by another firm - uses Markaby.

Markaby makes view templates look just like any other Ruby code and it is extremely intuitive: all I had to do was read this and I was good to go! I also like the way Markaby syntax can be used in helpers – Ryan Bates has produced another one of his fine RailsCasts on this very subject.

The only real downside I can see to using Markaby is its relatively slow speed especially when HAML is getting faster with each release.

Here are a few tips that I came up with for getting Markaby to generate XHTML the way I wanted it to.

Element classes and ids with hyphens

In Markaby you can easily define class and id attributes by calling methods on the container elements like so:

div.error { 'error' }
p.intro! 'welcome'

This generates the following XHTML:

<div class="error">error</div>
<p id="intro">welcome</p>

But this syntax can’t be used when you want the class or id attribute to use hyphens (which is my personal preference), for example these won’t work:

div.error-message { 'error' }
p.intro-text! 'welcome'

Both of these examples cause syntax errors:

This is because Ruby evaluates the hyphen as the subtraction operator. This shouldn’t really come as a surprise given that Markaby is just Ruby code, but it caused me a few moments of head scratching when I first came across the error.

The solution is thankfully simple: classes and ids can also be specified by passing them as parameters to the container element. So the correct code is:

div :class => 'error-message' do 'error' end
p 'welcome', :id => 'intro-text'

Generating empty elements

Let’s say you want to generate something like this:

<div class="floated">content</div>
<div class="clear"></div>
<div>some more content</div>

You might think that this would do the job:

div.floated "content"
div.clear
div "some more content"

But you’d be wrong – this is what you’ll get:

<div class="floated">content</div>
<div class="clear">
  <div>some more content</div>
</div>

As you can see the nesting of elements has gone wrong. Again this is an easy one to fix, just pass the container element an empty block like this:

div.clear {}

Capturing generated markup

Let’s say you have a two column blog page layout: the left column will contain headings and excerpts of each blog entry and the right column will contain a list of entry headings. You could do this:

div :class => 'left-column' do
  for entry in @entries do
    h3 entry.title
    p entry.excerpt
  end
end
div :class => 'right-column' do
  ul do
    for entry in @entries do
      li entry.title
    end
  end
end

This would do the trick, but if you’re like me then having two for loops iterating through the entries seems a bit unnecessary. It’d be nice to have one loop generating the content for both columns.

That’s where captures comes in. The capture method allows the XHTML generated by Markaby to be stored in an instance variable for use elsewhere in the template. Here’s the above example rewritten to use capture:

div :class => 'left-column' do
  @entry_list = ''
  for entry in @entries do
    h3 entry.title
    p entry.excerpt
    @entry_list += capture { li entry.title }
  end
end
div :class => 'right-column' do
  ul { @entry_list }
end

This can be simplified further as the capture method is not really required:

div :class => 'left-column' do
  @entry_list = ''
  for entry in @entries do
    h3 entry.title
    p entry.excerpt
    @entry_list += li entry.title
  end
end
div :class => 'right-column' do
  ul { @entry_list }
end

This is obviously a simple example, but it demonstrates how capturing output can be useful when optimising your templates.

Updated on 07 February 2019
First published by Rob Anderton on 11 November 2007
© Rob Anderton 2019
"Markaby tips" by Rob Anderton at TheWebFellas is licensed under a Creative Commons Attribution 4.0 International License.