Tag: web development

2008-04-12 15: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-23 15:03 UTC Why Rails is total overkill and why I love Rack

Rails is total overkill. It tries to do "everything" in a massive framework where major components are tightly intervowen. Smaller frameworks like Merb and Camping have already shown you don't NEED this. I argue you don't need a framework at all - you need highly cohesive, loosely coupled components. That is why I love Rack - it does one thing and does it well, and leave me to write applications, not learn frameworks.

Why I love Rack

Rack is beautiful in it's simplicity. I've posted a couple of Rack middleware classes that shows how simple it is to extend. (check out my Rack tag for more)

It struck a chord with me because what it tries to do is very limited; it's simple; its model encourages layering and compositions of cohesive individual component as opposed to what "frameworks" usually does.

Rack is not a framework. If you want a framework you can plug it into Rack. If you don't, you can write to the bare Rack environment.

"Framework" is to me an euphemism for "Gordian knot of interdependencies". It doesn't have to be that way, but it ends up being that way more often than not. If a framework is engineered explicitly to be just a collection of libraries that share minimal interdependencies and are useful by themselves, then I have no beef with it.

While there are many common needs for various web apps, they are however largely orthogonal, and can easily be supported via independent, highly cohesive libraries. This is the case for most domains where people promote frameworks. Let me give some examples related to web apps:

  • Sessions: The basic requirement for session handling is the ability to persist objects or pieces of data, and to tie that persistence to a key extracted from a cookie or CGI parameter. There's no reason for this to not consist of a self-contained module to handle the persistence, and a tiny adapter from the CGI environment (whether provided by Rack, the CGI class, or something else) to the persistence code. Why intermingle it with "framework" code?
  • Database handling: Ok, so Rails too does the right thing here (mostly) and ActiveRecord can indeed easily be used outside of Rails. There's just no reason for the ORM or other database code to be tied to a framework. But Rails tie you pretty intimately to ActiveRecord. If you buy into Rails, the assumption is you'll use ActiveRecord. Which sucks if you don't like ActiveRecord or it's not suitable for your application.
  • Request processing: Exactly what is it people want here? For me request processing involves parsing the CGI environment and presenting it nicely packaged up. Possibly handling uploads. Some escaping/unescaping. Rack::Request handles all I need there.
  • Rendering/views: The plethora of different rendering libraries generating HTML output demonstrates quite clearly this can be done separately.
  • Routing/dispatching: It's at most a Hash mapping regexp's to classes and/or method calls. Hardly an earth shattering invention. The routing class I use for this blog is about 40 lines, and it's only that big because it's full of bells and whistles. It also has four and only four requirements of the outside world: You must pass it path_info, request_method and an object that will be passed on to the classes it dispatches to; the classes you want to route to must know how to respond to methods corresponding to the values of request_method OR call (so a proc will work); the classes must know how to deal with the request object you pass in. Minimize coupling. Always. Even for trivial code.
  • Form handling: I've not seen many good approaches here. At Edgeio we put together a generic forms class that did go some way in reducing the typing by extracting the values needed from the request and generating the data needed by the view automatically. It's tens of lines of code at the most, and can be done with very few - if any - dependencies.

There are more bits and pieces, but common to them all is that no specific dependencies are needed - all of these components can, and have, been implemented in ways that makes it easy to plug them into whatever environment you have.

Why rails is total overkill

I can piece together all I need easily from libraries I like. I don't need (or want) Rails to dictate what I use:

IF I need sessions, there's a lot of libraries handling persistence, and tieing it into Rails is less than 10 lines of code, and it's less than 10 lines of code I write once and will reuse elsewhere (but generally I'm getting more and more negative to sessions - if you need them so often you can't just persist them in your database without worrying about performance, you have a code smell that makes scaling hard).

For ORM's I've picked Sequel for my blog, but there's a number of alternatives.

For request processing, just plain Rack::Request meets all my needs.

Rendering views? I rolled my own in about 30 lines of code that's sufficient for this blog - for something larger I'd pick one of the huge number of templating languages (up to and including XSL, which I've used in the past because it has some nice properties such as being able to feed the XML + XSL straight to a browser to let you see the raw data passed to the view in the browser with "show source" during debugging).

Routing/dispatching I as mentioned needed a whopping 40 lines or so for, and now I have a reusable component that will plug happily in if I ever need to replace Rack, or even if I replace everything else.

I'm sure any Rails fans reading this (all two of you, judging by my number of subscribers at this stage) will be fuming and be aching to complain about how many extra things Rails gives them. The problem is I don't need more. I've written web apps in many languages (including C++ - I kid you not) over the years, and the above are all the web specific components I've needed.

Beyond that there are certainly a large number of libraries that may be useful for specific types of apps. But none of them are specific to writing web applications. None of them need interdependencies with a web framework.

To sum it up: A difference in philosophy

Applications should be composed of components that show:

  • High cohesion: Each component should do one or a small number of things that are tightly related and do them well, rather than trying to do "everything".
  • Low coupling: You should be able to replace any component with another one without having to reimplement a ton of complex interfaces.

Rails fail miserably there, and that makes Rails overkill to me. This blog is as small as typical "demo" Rails apps, and yet it doesn't use any framework, just independent libraries such as Sequel for the models, Hpricot for assorted HTML mangling etc.

It's only coupling to Rack is that it expects something to call the "call" method of the routing class with something resembling a CGI environment. Changing it to use the CGI class is about 10 lines of code. Changing it to bypass both Rack and the CGI class and parse the bits it needs of it's own environment is perhaps another 20.

Half the code is a collection of tiny reusable components - some are Rack middleware whose only dependency on Rack is the calling convention (one method call and the expected format of the result), and some are things like the 40 line dispatches.

That's why Rails is overkill: You can easily build web applications without the "magic", and without the interdependencies and all the rest that comes with it.

Could some things in Rails be useful? Yes, there are a lot of useful things in Rails, but they could practically all have been done as independent components, and we'd be all the better for it, being able to pick and choose the pieces we need rather than dragging in a huge framework and tons of dependencies and all kinds of other baggage that I for one do not want.



2008-03-20 19:44 UTC Pet peeve: Exposing file extensions on the web

Posted in: ,
I keep coming across sites with pages like "/location.asp" or "/Home.aspx". I absolutely hate it.

What happens when you want to redevelop your site in another language? Do you litter 301 redirects all over the place? Or just break all your old links? Or force your webserver to treat pages ending in .asp and .aspx as PHP (or vice versa)

File extensions are not evil, but they should be used sparingly, and if you use them they should be used to represent content types served, not platform used to generate the content.

I feel particularly strongly about this today, as I've just finished a 30 page search engine optimization report for a Aardvark Media customer who's been with us for a couple of years now, yet still see people trying to access assorted ASP scripts from their old site.

The base names are often the same, but the extension is gone.

I know some of our "legacy" sites still expose ".php", but it's one of the things I'll veto for any new development.



Older Entries

About me

E-mail: vidar@hokstad.com Skype: vhokstad
Twitter: 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 and we just had our first child, Tristan Ikemefuna Hokstad.

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.

Twitter Updates

    follow me on Twitter