Mustache for your mail merge

By: on October 31, 2011

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" programminglanguages 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.

FacebookTwitterGoogle+

Post a comment

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>