Sinatra View Engines - Effigy and Mustache
Earlier this year, I began working on a Ruby side-project, mainly as an excuse to learn Sinatra, MongoDB, and Heroku. I also wanted to try out a new view templating engine, as I find that ERB views aren’t exactly the most readable examples of code. (Properly using partials can help alleviate this problem, but I just don’t like to see Ruby mixed in with HTML tags). Many Sinatra tutorials use Haml, but I’m just not comfortable with Haml’s abandonment of HTML syntax - I actually like HTML, am comfortable with it, and don’t find typing full tags to slow down my coding (especially when using tab completion in TextMate). I looked for something that allowed me to write templates in pure HTML, and keep actual view logic separately enclosed in Ruby.
One solution particularly appealed to me: a new project called Effigy, written by Joe Ferris of thoughtbot. Effigy view templates are pure HTML, and don’t even include tokens. Instead, view transformation occurs within a pure Ruby file, which uses jQuery-style selectors to manipulate template elements and populate them with data. The magic happens in a transform method, which just needs to be overridden in view classes:
After working with Effigy for a few months, I found that I really appreciated its clean separation of concerns. Effigy really shines in situations where your front-end developers and Ruby developers are cleanly separated: the front-end team can build complete HTML mockups of a page, populated with dummy data or lorem ipsum placeholders, while the Ruby developers can focus entirely on view logic. I also appreciate the jQuery style selectors (powered under the hood by Nokogiri); since I’m coding jQuery anyway, it’s not a stretch to think in terms of these selectors.
After having to abandon the project for a few months, however, I realized that I no longer wanted to continue with Effigy as my view engine, for several reasons. First and foremost, Effigy view logic can be a bit verbose: since you’re basically performing a bunch of find-and-replace logic, views based on iterating through a collection can be ugly to read through. And while the HTML templates are completely Ruby agnostic, the relationship doesn’t work both ways: Ruby view logic is tightly coupled to the HTML implementation, as you need to refer to specific IDs and classes in your Effigy find statements. Things can get out of control very quickly, as the example below indicates:
Thankfully, refactoring away from Effigy hasn’t proven to be that difficult - a major benefit of the “separation of concerns” that Effigy espouses. I’ve switched to using Mustache.rb, and I’ve been really happy with the move. Why Mustache? It accomplishes the same separation of HTML and Ruby that Effigy does, but in a slightly cleaner way: Mustache HTML templates use a very limited number of tokens which refer to methods or variables in the view code. For example, a template with {{foo}} can refer to either @foo or def foo in the template’s matching view.rb file. There’s even support for if/else and collections within the tokens. Mustache also makes using partials easy, and bakes caching into the view engine. Finally, Mustache templates are simple to move from one language to another - Mustache.js is increasingly popular, and there are Mustache implementations for any language I’d want to work with - Scala, Python, PHP, Java, etc.
If you’re starting a new Ruby project, definitely give Mustache a try. If you run into any problems setting things up, feel free to shoot me a question on Twitter.