Agile Ajax

Down with HTML + Code Markup!

I'm looking at you, ERb...

div_tag-1.jpg

I just did something in a Rails project that made me very happy -- I wrote a lot of helper methods. I had a whole mess of ERb managing an index page with pagination, sorting, quick search, and so on, all of which was going to need to be more or less duplicated for several controllers.

This promised to be annoying, so I started to push some of the HTML/ERb code up to helper methods with an eye toward reusing them. Eventually, I was able to convert the whole thing to a series of helper methods -- the view page is just a single line calling the top-level helper methods. And I smiled.

A little history. Once upon a time, I wrote my first Java Servlet application, which I think was a news and comments forum. Servlets were brand-new, and JSP's were either not quite out yet, or were unsuitable for some reason. I wrote the entire view layer using a library I wrote that encapsulated HTML tags, like HTMLAnchorTag.new().setReference("http://whatever").append("Click Here").toString();

It was, I admit, absurdly verbose -- you should have seen it when CSS styles were involved... (I had an SQL generating package that was somewhat better), but I liked the the code it produced. In particular, the library was very good for highly structured web pages -- I tended to have aggregated HTML classes or methods correspond to specific objects that were displayed on the pages.

Anyway, in the fullness of time, I switched back to the JSP/Velocity/FreeMarker/ERb/ASP/PHP style where the HTML is interspersed with the display logic, because, let's face it, it's way less verbose than declaring each HTML tag as a Java object. But I've never felt like it's the best way to specify a web view layer.

For one thing, the style encourages long, unfactored code, with logic and markup intertangled. For another, you get really ugly constructs when you have to insert markup inside HTML:

<div id="<% dom_id(@thing) %>">

That %>"> structure drives me batty -- I always think it's a typo.

Plus I never know how to indent things -- the HTML structure and the logical structure clash and the markup tags interrupt the layout as well:

<table>
<tr>
<th>Header</th>
<th>Header></th>
</tr>
<% @items.each do |item| %>
<tr>
<td></td>
</tr>
<% end>

It always bugs me that the different <tr> tags are not lined up. And I never know whether to indent further ERb lines to line up with the <% tag or the actual start of the Ruby code. Petty, sure, but I've always felt that problems laying code out indicate a problem in the logical structure of the code.

So, I'm trying the current experiment, to put as much of the view layer as possible in Ruby code, helpers, and as little as possible as raw HTML and ERb. So far I like it.

Benefits

  • My refactoring impulse kicks in, and I wind up with nice, reusable ten-line helper methods for common HTML structures, such as tables based on ActiveRecord objects

  • Each chunk of code has a logical label -- the name of it's helper method, allowing the code to signal intent.

  • Using content_tag means no more missed end tags.

Costs

  • If you do it wrong, the helper code can be a little tricky to read.

  • It's also potentially less accessible to a CSS designer who doesn't know Ruby.

  • Rails doesn't fully support the style. It'd be nice to have something like render :helper => helper_method(@item) to make it easy to call a one-line helper from the controller. As it is, it's easier to create a one-line .erb file.

  • Also, Rails block helpers like form_for don't really translate well to being called from helper methods, since they typically inject output directly into the ERb stream, rather than returning a string. This makes it awkward to call those helpers from inside other helpers, but it's possible I just haven't found the right magic words yet.

A lot of Rails developers have been trying to find better view structures -- Jay Field's presenter pattern is in the new Advanced Rails Recipes, Marcel Molina was working on something for more object-oriented views -- but nobody seems to have hit on the sweet spot yet. Still looking.


Please check out my book, Professional Ruby on Rails.

Topics:

Comments: 7 so far

  1. Have you looked into using HAML instead of ERb? Your div example would look something like

    .thing{:id => dom_id(@thing)}

    Comment by Brian, Friday, May 16, 2008 @ 6:21 pm

  2. I tested HAML, Markaby, and Liquid in the book. Markaby is very attractive, but reportedly too slow for a high-traffic system. Liquid is most suited to a case where you need to prevent designers from accessing some functionality. HAML I found kind of opaque and hard to read.

    Comment by Anonymous, Friday, May 16, 2008 @ 8:37 pm

  3. Having to use template language syntax between the brackets drives me nuts as well, especially when I see someone drop a whole if statement in there. I don’t use rails anymore but I am currently in the middle of refactoring ALL our front-end code at work (Freemarker) and went from simply creating a css framework to fix some inconsistencies I was noticing (not to mention trim ~1600 lines of rounded corner rules down to about 80 for the entire site) to building a series of macros/helper functions so there’s no need to write yet another “Top Photos” module for “new page X”. While I did this all mostly to speed up dev time of new features by introducing a framework of common elements/modules, it will also help avoid introducing bad markup since the “new hire” only needs to call a macro.

    Comment by Jesse, Friday, May 16, 2008 @ 9:48 pm

  4. How about Kwartz?
    Kwartz separates the presentation logic from the HTML template in the same way CSS separates design from HTML.
    As the result, template is pure HTML and it’s design is never broken.
    In addition, Kwartz can generate eRuby file from HTML template.
    I think you should try it if you are looking for the best solution.

    Comment by makoto kuwata, Friday, May 16, 2008 @ 10:45 pm

  5. Have a look at Erector: http://erector.rubyforge.org/

    Comment by Bob, Saturday, May 17, 2008 @ 1:12 am

  6. You must have a look at the wicket framework. It’s one of the reasons I love wicket - separate java code from html.

    Comment by Shams Mahmood, Saturday, May 17, 2008 @ 8:19 am

  7. Can I ask who or what you were building the $link.’click here’ app for?

    It’s a long shot but the server logs for one of our sites has been peppered with
    GET /recipes/collections/easy/click%20here HTTP/1.1
    GET /recipes/1266/click%20here HTTP/1.1
    GET /page/delicious/click%20here HTTP/1.1
    etc. requests the past couple of days and we have no idea what’s spawning them. - half of the requests don’t resolve to proper pages…

    Comment by tim hj, Thursday, June 5, 2008 @ 3:27 am

Leave a comment

Powered by WP Hashcash

About Pathfinder

  • We design and build extraordinary applications for companies looking to make the next great idea a reality.
  • learn more

Topics

WordPress

Comments about this site: info@pathf.com