technology from back to front

Mustache for your mail merge

At LShift we like to program on blackboards using untyped lambda calculus,
and we enter code into a computer only once we have a truly generic solution
to a problem. However, most of the time we need to earn money so that we can
eat and wear clothes other than LShift t-shirts – this usually involves
compromising our principled approach and using "real" programming
languages and libraries.

This can be quite painful! In my experience all real world projects need to
produce output for a customer and this usually uses a technology called
"mail merge" but as we are technical people we use the more
technical name of "templating" (If you are elderly and not a
computer scientist it is best to think of it as mail merge, this will have
been an activity you read about in PCW magazines when you were a spotty
teenager and hoped to never carry out and now looking back over your
illustrious career you have realised that you have spent most of your time
performing mail merge poorly). Templating sucks!

As we are rapidly moving into Movember
I will briefly describe templating with mustache (this is how colonial people
spell moustache, but searching for moustache on github will produce an
excellent Clojure library not a templating system). I propose that if you
are programming in Ruby,
Mustache sucks less than ERB and
will support my proposal with some examples.

As I said previously templating sucks! It especially sucks if you care
about the formatting of your output which is why I call templating mail
merge. If you received a printed letter from your electricity supplier and
it went,

Dear    Valued 

     Customer, 

Your request for
 a further three phase supply to your premises

is denied
  as we fear that you have upset the villagers
with your reanimation experiments.

you would probably be wondering about the extra spaces and carriage return
in the text. Most of the time in HTML you wouldn’t notice because browsers
eat whitespace, however if you were templating printed material or code it
can be quite painful.

Lets look at an example of this using ERB. We will define a simple Ruby
class to hold sections that have a name and may contain subsections.

class Section
  attr_reader :name, :subsections
  def initialize(name, subsections = nil)
    @name  = name
    @subsections = subsections
  end
end

Here is the ERB to render the output:

<% s.sections.each do |section| %>
This is section <%= section.name %>
<% if section.subsections %>
  <% section.subsections.each do |subsection| %>
  This is subsection <%= subsection.name %>
  <% end %>
<% end %>
<% end %>

Which I render like this:

template1 = ERB.new(File.read("simple1.erb"), 0, '<>')
puts "======================================"
puts template1.result
puts "======================================"

To produce:

======================================
This is section one
This is section two
 
  This is subsection two-a
 
This is section three

======================================

That output doesn’t look brilliant to me! I can feel a bug being raised in
the issue tracker already, it really shouldn’t have those empty lines in the
output.

If I modify the ERB I can do better:

<% s.sections.each do |section| %>
This is section <%= section.name %>
<% if section.subsections %>
<% section.subsections.each do |subsection| %>
  This is subsection <%= subsection.name %>
<% end %>
<% end %>
<% end %>

Which produces:

======================================
This is section one
This is section two
   This is subsection two-a
This is section three
======================================

Perfect output, but the ERB template looks a bit fragile, three end tags all
in a row with no indentation to guide you will probably lead to difficult
maintenance. The ERB templates I am currently maintaining are much more complex
than the one I have used here and indentation really does help to make them
readable.

Now for mustache! The template looks like this:

{{#sections}}
This is section {{name}}
  {{#subsections}}
  This is subsection {{name}}
  {{/subsections}}
{{/sections}}

We have to do a small amount more work to generate the output like this:

class Simple < Mustache
  self.template_path = File.dirname(__FILE__)

  def sections
    Array[
      Section.new("one"),
      Section.new("two", Array[Section.new("two-a")]),
      Section.new("three")]
  end
end

s = Simple.new
puts "======================================"
puts s.render
puts "======================================"

The code produces perfect output:

======================================
This is section one
This is section two
   This is subsection two-a
This is section three
======================================

The template also looks more maintainable than the equivalent ERB. However,
you can still break the output quite easily with a very small change like this:

{{#sections}}
This is section {{name}}
  {{#subsections}}This is subsection {{name}}{{/subsections}}
{{/sections}}

Which produces this broken output:

======================================
This is section one
 
This is section two
 This is subsection two-a
This is section three
   
======================================

So it is best to keep your mustache sections on seperate lines to avoid
extraneous whitespace. In summary mustache is probably easier and will
produce cleaner output that ERB if you are performing a mail merge.
Additionally mustache is cross-platform and has support for a large
range of esoteric languages if you are tired of programming in Ruby.

by
tim
on
31/10/11
 
 


nine − = 8

2000-14 LShift Ltd, 1st Floor, Hoxton Point, 6 Rufus Street, London, N1 6PE, UK+44 (0)20 7729 7060   Contact us