- We design and build extraordinary applications for companies looking to make the next great idea a reality.
- learn more
HTML + Code Markup: Threat or Menace, Part Two

Last week's post about ERb and other HTML + Markup view languages got five actual comments. By the standards of my recent posts, that's practically a mob.
Most of the commenters wanted me to look at their favorite view tool, which I dutifully did. I then went out and did something completely different.
I covered HAML and Markaby a bit in Professional Ruby on Rails. Markaby I like conceptually, but the concerns about it's structure and speed have kept me from using it more (although the solution I did pick is probably not a speed demon either). I find HAML really opaque, but if it makes sense to you, more power to you. Erector is in some sense an enhanced Markaby.
Commenters also wanted me to look at Kwartz and Wicket, which are both tools where the template is valid HTML, but a special attribute namespace is used to tell the templating system to insert content and logic. I like the idea in theory, but anything that uses XML namespaces makes me break out in hives (to be fair, the Wicket folk say they aren't using XML, just the same namespace syntax). It's a little more high-ceremony then I needed.
Looking at all these solutions was quite helpful in making me think about what I actually wanted. One issue I had with Erector, and to some extent Markaby, is that the entire output page is an object -- to use a layout you subclass it. Using inheritance in this case doesn't work for me, I'm having a hard time seeing the layout/page relationship as IS-A, it really feels like a HAS-A relationship to me. Besides, I like the ability to use HTML for static parts and where appropriate -- I still haven't seen a markup language that handles a mixed mode case like this very well:
<div>This is <b>the</b> <i>best</> tool</div>
What I really want is the ability to treat chunks of output as objects and drop them into the output with a single line of code, and be able to cleanly specify the HTML related to the object in Ruby code. This is the Presenter pattern, and there have been a couple of different attempts to integrate it into Rails.
I don't quite have a full presenter pattern, but I do have a way of generating the HTML that I like. It's basically a wrapper around the Rails content_tag helper, but fixing two problems I had with content_tag.
The content_tag method takes an optional block which is evaluated as the contents of the tag. However, since it's an ordinary Ruby block, only the last value is returned. This is a problem if you are composing multiple subtags inside the block. You need to concatinate or join the subtags together, otherwise only the last one is used, making the code inside the block ugly. Also, the block version is dependent on ERb being around in certain cases, which makes content_tag hard to unit test.
My current solution is a Ruby evolution of the tag-generation library I mentioned in the last post. This being Ruby, it's about 25 lines of code.
Usage looks something like this:
def object_to_vertical_rows(obj, *rows)
rows.map do |method, caption|
Html.tr do |tr|
caption = method.to_s.humanize unless caption
tr < "caption")
tr << Html.td(obj.send(method))
end
end
end
Html is a class with a tag name, a content array, and an options hash. There's class level method_missing function that just creates a new instance with method name, so Html.tr prepares a <tr> tag pair. The content of the tag can be specified as the second argument, or built up in the block. The block takes the tag being built as it's argument -- giving that block variable the same name as the tag is a trick to make the block more readable. Any options passed to the constructor are treated as attributes.
Inside the block, content can be added to the tag using the << operator, which just contatinates the new content to the existing content, eliminating the need for ugly join code in the block. You can also assign content to the content attribute directly. Inside the block, you can also assign attributes -- it's another method_missing deal, where any unknown method is treated as an attribute of the resulting HTML output.
Here's what I like about this setup:
- It's meeting my needs -- I can easily convert from my ERb to the Html class. It matches how I think about HTML being constructed
- The code is, to my eyes at least, significantly easier to read and follow then the equivalent code written with
content_tag. - It's lightweight -- I don't have to convert everything to it, I can use it where appropriate and ignore it otherwise.
- It's much easier to test then
content_tagwith block.
Here's what I don't like about it:
- It's kind of idiosyncratic, and I'm not sure it's enough of an advantage over existing structures to justify the added complexity of a new tag generator.
- I haven't done a speed check, but it's probably not all that fast. I suspect it's a bit slower than
content_tag, although. - Having to specify the tag name again as the block argument is a little goofy, although I thought it was less goofy than the
instance_evalkind of magic needed to reduce it completely. On the plus side, it does have a nice explicitness to it.
Anyway, here's the current implementation of the class -- if there's interest, I'll throw it on GitHub.
class Html
include ActionView::Helpers::TagHelper
attr_accessor :tag, :content, :options
def self.method_missing(name, *args, &block)
Html.new(name, *args, &block)
end
def initialize(tag, content = [], options = {}, &block)
@tag = tag
if content.is_a? Hash
@options = content
@content = []
else
@content = [content]
@options = options
end
block.call(self) if block
end
def method_missing(name, args)
options[name] = args
end
def <<(text)
content << text
content.compact.flatten
end
def to_s
content_tag(tag, content.join("\n"), options)
end
def to_str
to_s
end
end
Topics: Ruby on Rails
Comments: 5 so far
Leave a comment
About Pathfinder
Recent
- Rails ThreatDown!
- Automated Deployments Rock
- Bandwidth profiling Flex projects and more with Charles
- iPhone SDK: UIViewController Testing & TDD
- Icons are evil; so are menus - unless you do them right
- The Truth About Designing For Security
- GWT, Gadgets and OpenSocial, Part 2
- Has Many has_many: A Refactoring Story
- The Hidden Power of Canvas
- Review of fixture_replacement2 plugin
Archives
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
- April 2006
- March 2006


Looks good to me. I kinda like the syntax and how it flows. I would like it even more if it didn’t depended on ActionView. I might need to fork it someday!
AEM
Comment by Adrian Madrid, Friday, May 23, 2008 @ 5:37 pm
I do hope to break the dependency on content_tag, but it’s a convenient way to get the markup right.
Comment by Noel Rappin, Friday, May 23, 2008 @ 6:21 pm
[...] experience at a Birds of a Feather hosted by Pivotal Labs, where I got discussing view layers and my issues with Erector with the actual developers of Erector. That was a fun [...]
Pingback by Pathfinder Development » RailsConf 2008: A Belated Look Back, Friday, June 13, 2008 @ 4:27 pm
[...] wrote the view code for this using the HTML code generating helper I wrote about a few weeks ago. I still like the resulting code, although it has been called, and I [...]
Pingback by Pathfinder Development » Project Website, Part Two: Simple jQuery With Rails, Monday, July 14, 2008 @ 11:33 pm
[...] I’m also interested to see how this works with my Html generator mini-library [...]
Pingback by Pathfinder Development » Rails 2.2 For Me And For You, Monday, November 3, 2008 @ 1:50 pm