Sunday, March 11, 2007

Ruby on Rails - Part 3

Blocks are an integral part of the Ruby language. While some aspects of blocks are easy to understand, they can be a source of confusion for developers new to Ruby. With a background in C style languages, I tried to understand Ruby blocks within the context of C function pointers and Java anonymous inner classes.

What is a block?

A block is an object that contains Ruby code, and the context necessary to execute it. In other words, a Ruby block is a method without a name. My first exposure to Ruby blocks was through iterators. This was an easy concept to understand and is illustrated by the following:
"abc".each_byte {|c| printf "(%c)", c }
The above snippet would result in the following output: (a)(b)(c).

What can I do with it?

The openEPRS project makes use of the Redbox plugin to create modal 'dialogs' without resorting to opening a new browser window. I wanted to dress up Redbox so it would look more like an actual window (caption with controls and a drop shadow). While learning RoR, I thought it was rather elegant that many of the helpers that I was using in my .rhtml templates could enclose sections of HTML. I thought this would be a good way to create a helper to wrap my Redbox content in a 'window'. This resulted in the following:
def dialog_tag(title, options = {}, &block)
  # Check if a content block was passed
  return unless block_given?

  # Check width and height options
  width = options[:width] || '1px'
  height = options[:height] || '1px'

  # Content
  content = capture(&block)

  # Header
  header = ... HTML markup

  # Footer
  footer = ... HTML markup

  # Build dialog
  concat(header, block.binding)
  concat(content, block.binding)
  concat(footer, block.binding)
The secret is with the &block parameter in my helper. This lets you wrap your content using the following syntax:
<% dialog_tag('Caption Text') do %>;
... HTML markup
<% end %>
My effort to explain Ruby blocks is mediocre at best but I wanted to show an example of how I made practical use of this language feature. I am still learning this powerful scripting language and it will take some time to master it. The positive is that I don't know how I managed to get anything done before RoR. For the tactical web application using anything else would be too painful.