Vidar Hokstad V2.0

Home Blog

Tag: frameworks

2008-04-12 11:19 UTC Mini reviews of 19 Ruby template engines

I've seen lots of template systems in Ruby, but haven't been really been happy with any of them. Over the last few months or so I've kept notes of the ones I looked at. This is the list I came up with, and some comments on each. But first a disclaimer:

I have NOT spent a lot of time looking at these - there are far too many for me to have time to go into a lot of detail for each of them. Some I know well, many I only know from a cursory review, so don't write an engine off just based on my comments. Also, I very much welcome corrections (or additions) in the comments

Wildcards

These don't fit in any of the other groups below.

  • Radius.
    Pro: Radius lets you define your own "tags" - the input is "almost XML" (it uses namespace prefixes, but relies on the prefix value, not the namespaceURI it's tied to - I don't know if that's intentional or lack of understanding of XML), which should let a lot of editors work well with it, and possibly (if you're careful) roundtrip it into web dev tools. It's also designed to be able to output any text, so it's not tied to HTML
    Con: It's not actually a templating language, but a tool for creating your own template systems (that certainly makes it more flexible, though).

  • HAML.
    Pro: Very compact syntax.
    Con: Whitespace matters. I ignore Python because of that (even though, as any Pythonista will tell you it's not nearly as bad as people say it is, which is probably true) - HAML would have to be a hell of a lot more compelling to overcome my innate dislike for that. It also just doesn't "feel right" to me. I'm a syntax snob, and not afraid to admit it: Either I like it or I don't. If I don't like the syntax I won't touch the language with a ten meter pole no matter what.

  • cs/Template.
    Pro: Fast (written in C). Uses paths into a tree of objects (like TAL/Amrita style engines). Not tied to HTML/XML. Almost safe to for external content (you'd need to disable "eval")
    Con: Not pure Ruby. Looks like you'd need to dip down into using the eval mechanism fairly frequently as control structures supported directly look fairly limited. Doesn't seem to allow user extension of the "macro"'s provided without dipping into the code, which would negate this point

eRuby style

Ruby code and text intervowen.

  • ERB
    Pro: Part of the Ruby standard library, and so it adds no external dependencies. Con: Templates are not much more than a string with Ruby interpolated. The Ruby is sprinkled in as "tags", but those tags are not valid XML tags, so editors that have strict XML modes will treat the tags as content (whether that's a good or a bad thing is purely subjective, I think - I don't like it). If you're using ERB, what's the benefit over just using standard Ruby interpolation syntax ( #{ ruby code here } )? Not much, as far as I can tell, other than some basic convenience functionality, and some very limited safety features.
  • eRuby
    Pro: Faster than ERB
    Con: External dependency. C extension
  • Erubis
    Pro: Faster than ERB / eRuby. Automatic escaping of variables possible
    Con: Same as for ERB
  • Galena
    Pro: Embed templates directly in your Ruby classes. If you for whatever reason don't want to split your views out from your code, Galena at least lets you format the text in a somewhat cleaner way than lots of variable interpolation.
    Con: Tight coupling of code and data. Even tighter than with "cleanly" written ERb if there is such a thing...
  • Tenjin
    Pro: Exists for multiple languages (Python, PHP, Perl, Javascript(!), Ruby, Java) with mostly the same syntax. Lots of features
    Con: Embedded code as the other ERb style languages, and this largely negates having it in multiple languages.

Liquid style

Text and "code" in a template language that is generally designed to be "safe" to varying degrees, up to and including allowing users to submit templated data without enabling execution of arbitrary code.

  • Liquid Markup.
    Pro: Aims to be safe, by preventing people editing the templates from running arbitrary code on your servers.
    Con: Another "language" to learn, though simple. Syntax for attributes etc. deviates from conventions shared by many other Ruby template languages.

  • Ruty
    Pro: Seems to be safe, by preventing arbitrary code or infinite loops. Very flexible set of filters. Template "inheritance". Mechanism to allow passing arbitrary "context" objects in without exposing unsafe methods to the temples.
    Con: Same as for Liquid

  • PageTemplate
    Pro: Seems to be safe. Looks like a sort of mix between a Liquid style template language and Textile style (apparently inspired by Perl's HTML:::Template, which I haven't used/looked at)
    Con: Not sure - personally the syntax didn't do it for me.

Amrita/TAL style

These look like pure XML (though many TAL-like template systems for Ruby and other languages violate XML expectations they are often close enough to be manipulated with a non-validating XML parser).

  • Amrita
    Pro: No code in the templates. Uses id's on the tags to tie the template to the model data. Can be "compiled" to Ruby like TAL
    Con: Uses REXML (slow) for XML parsing. Very basic functionality unless you provide Proc objects as part of the model data - like Radius it probably needs an extra layer to provide more advanced functionality for use in typical applications if you want to retain a clean model/view separation.
  • Amrita2
    Pro: "Compiles" to Ruby like PHPTal does rather than parsing templates each time. Much more flexible than the original Amrita. "Filters" can be applied to values to be output to handle rendering/formatting of values etc.
    Con: Complex (including supporting a really freaky syntax called AMXML as an alternative to the more TAL-like syntax). Seems to loose the relative safety of TAL-type templates by having several mechanisms for embedding Ruby. Too many ways of doing things.

  • Kwartz
    Pro: Exists in both a Ruby and PHP version using the same syntax for the templates, it seems. Appears to be very flexible. Should roundtrip easily to HTML editors. No logic at all in the templates Con: "Compiles" to ERb. No logic at all in the templates (yeah, I know, this can be a good thing too - depending on your use-case - the Kwartz approach is a bit extreme, though it seems). The logic/code uses a second template syntax instead of being just a file of valid code.

Markaby style

These tend to look like Ruby block notation, and make markup look purely like code.

  • Markaby.
    Pro: Markup as Ruby. Very simple and follows Ruby DSL conventions
    Con: Markup as Ruby... Inside a Markaby template "self" is the Markaby builder.
  • Maline.
    Pro: Simple to read; Follows fairly standard Ruby DSL conventions.
    Con: Does it actually offer anything "new" compared to Markaby and others that use almost exactly the same block syntax? I can't see any differentiating factors (I haven't looked very hard, though), but the author is clearly aware of Markaby (it's mentioned on the site), so I'm sure he has his reasons.
  • Builder::XmlMarkup
    Pro: Very small and simple. Comes bundled with Rails if that's what you're using.
    Con: Limited to XML generation (but that can of course also be a plus if it's just what you need)
    (Note: This originally said Builder was tied to Rails - corrected based on a comment below)

Wiki / Markdown / Textile style

These are "plaintext" or wiki style markup engines that aim to turn reasonably natural text into HTML or other output and may not have much in terms of variable expansion etc. as that's not their purpose. They will typically be unsuitable as a view templating system, but are useful as 'part of the arsenal' to handle markup of user generated content in a safe way.

  • RedCloth
    Pro: Textile for Ruby - "Plaintext like" / wiki type markup. Great for comments interfaces etc. to get mostly natural input without having to make people write HTML.
    Con: Not a full featured template language (which is ok - it's focus is on turning text into HTML). Syntax seems slightly out of tune with how I'd write plain text, and so it's still yet another markup to learn.
  • BlueCloth
    Pro: Markdown for Ruby - Platext / wiki type markup. Very similar to Textile / RedCloth in target, but to me Markdown syntax feels more natural for some types of text.
    Con: Not a full template language (which again isn't it's goal).

Seemingly dead projects (with or without code available)

In addition to the 19 above, I've come across a number of projects that appear to be dead, dormant or just haven't gotten properly started yet. I haven't looked more closely at them, but have included the links here. Descriptions are from their web-pages.


2008-03-24 16:30 UTC URLs do not belong in the Views

Posted in: , , ,
It's bothered me for some time to hardcode URLs in my views. It means that if I want to revise the linking structure, I may need to modify the views in a huge number of places. At the same time I don't like the thought of putting it in the model either.

In the entry Enforcing Strict Model-View Separation in Template Engines I point to an interview with, and a paper by, Terence Parr that articulated this issue much better than I had fleshed it out in my mind.

He also proposed a solution: Introduce an extra layer - Renderers - that turn model objects or attributes into a displayable format. An example might be formatting a date string the appropriate way.

His work is centered on Java, and so the solution he proposes (see section 8.1 in his paper) is suggesting having the controller wrapping attributes of the model in separate objects. This is clearly the most flexible solution, in that it allows different controllers to provide different renderers, or use different renderers at different times.

How does this apply to the URL issue? It would be trivial to wrap model objects with a renderer who knows how to turn the model object into a URL referring to it. As an experiment I tried extracting the URL's for the Ruby app running this blog, and it showed me two things:

  • It's certainly doable.
  • It's a useful exercise even if I ultimately don't make the change, in that it exposed areas where I clearly hadn't thought the linking structure through very well - especially it made me notice areas in my admin code that could be made far more restful and consistent.

A nice thing with Ruby, though, is also that while you lose some flexibility if you don't wrap the objects, you can achieve much of the same separation by reopening classes. Meta-programming techniques and DSL techniques also means that you could make it very easy to add this type of functionality in a way very close to aspect oriented programming, containing all the URL generating code in a single location.

Which lead me to think that it would be nice if I could combine this with my routing, but I'm not sure if that'd be good or not - it would lead to intermingling concepts relating to the controllers and the model.

Does the URLs even belong tied to the model, and not in the controllers?

It's a tricky situation. On one hand, the controllers should handle the overall interaction. On the other hand, in all the web applications I've worked on the systems have been very data centric, and URL schemes have always revolved around the model. REST also favors a data centric approach.

But this is less of a problem than it might seem at first if you first employ separation of concerns by clearly handling the URL formatting either in a separate renderer class or as a separate aspect of the model classes through reopening the classes.

Especially if you pass a renderer (or wrap the model objects that gets passed to the view in a renderer object), the controller remains in the driving seat completely. Imagine an API like this for the view:

renderer.url(some_model_object)

Interesting opportunities does open up to tie this to the routing and still relatively loosely couple the classes. In fact, I would argue that a method like this reduces coupling between the controller and views: If you put URLs in your views, and you change the routing or what aspects are handled by what controllers, the URLs may change and the views may have to change with them. Contain the URLs in a rendering object passed from the controller, and you centralize those changes.

If the routing mechanism is designed to do it, it could conceivably provide a rendering class if the routing information is extended somewhat. On this blog "/tag/(.*)" maps to the Tag model class, and the (.*) group refers to the "name" attribute of the Tag model. If the router instead of mapping /tag/(.*) only to a controller, also contained the knowledge of which model and attribute the static and dynamic parts of the URL map to (if any), then the rendering could be automated.

Arguably, the router is part of the controller infrastructure (technically you'd call it a front controller) and centralizing limited knowledge of the model there is not a big concern, as long as this knowledge is provided by the application and not encoded in the routing component itself.

To take an example from my current router for this blog, suppose I turned this:

  map '/tag/(.*)',      C::TagController
  map '/(.*)',          C::ShowItem

.. into this:

  map '/tag/(.*)',      C::TagController, M::Tag, :name
  map '/(.*)',          C::ShowItem, M::Item, :url

.. to denote that our hypothetical renderer should turn renderer.url(some_item_object) into "/#{some_item_object.url}" and renderer.url(some_tag_object) into "/tag/#{some_tag_object.name}"

An alternative would be to change from straight regexps to something requiring a bit more parsing:

  map '/tag/{M::Tag.name}', C::TagController

... which also opens up the possibility of passing an already instantiated model object in to the controller. The downside of that route is that it requires the dispatcher to know how to create model objects, which either means it needs a factory or it would become tied to a specific mechanism for creating model objects. WIth that choice in mind the earlier syntax example seems more attractive - you trade a little bit of simplicitly in the routing for a whole lot reduction in coupling.


2008-03-17 00:00 UTC My blog, version 2

Posted in: , ,
I started and ended my first blog back in 2005. What caused the demise of my blog later that year was the workload I ended up with as we started preparing to launch Edgeio during evenings and weekends while I was still at Yahoo.

It's time to give it a go again, though I'm still extremely busy... Nothing like some pressure.

As last time I expect I'll end up writing a mix of everything on my mind ranging from random sites I like (though the Stumbleupon feed on the right hand side will take most of that) to politics, technology and of course extreme geekery (I have a lot of notes on a hobby project to bootstrap a compiler - expect lengthy posts with copious amount of Ruby and x86 assembler at some point...)

I also expect to make the occasional post about the company I work at, a great London web development agency called Aardvark Media, as well as any startups I meddle with - currently SpatialQ, where I'm on the board, and Skoach (where I'm only providing occasional advice)


Older Entries

About me

E-mail: vidar@hokstad.com
Skype: vhokstad
View my LinkedIn profile

I was born April 21st, 1975, in Oslo, Norway. Since 2000 I've been living in London, UK. I'm married.

I'm working for Aardvark Media as Director of Technology. I'm also currently on the board of SpatialQ, a startup in the GIS space, and an advisor to Skoach, a startup doing a time management app for people with ADD.

Categories

StumbleUpon My link page

(Links I have stumbled and like)