h

Being Agile

Pete Hodgson's blurgh

Introducing Noguchi

Generating HTML tables in ruby has always seemed like more of a hassle than it should be. Most of the times that I’ve had to do it I’ve been a little frustrated with how, well, ugly the view code looks. So, I decided I’d try and create a nicer way to build tables. The end result is a small table creation library called Noguchi. Given a set of data and some optional configuration it will render a table as HTML or CSV.

Show me!

Here are some quick examples of the kind of things you can do with Noguchi. There are more features than I will show here; for more details check out the README in the library’s github repo

Creating a simple table from ActiveRecord model instances

table = Noguchi.table_for(users)
table.render

generates

NameAgeSex
Jenny24F
Dave32M
Hank27M

Rendering CSV

table = Noguchi.table_for(users)
table.render_as_csv

generates

name,age,sex
Jenny,24,F
Dave,32,M
Hank,27,M

Rendering collections of hashes

fruits = [
  { :name => 'banana', :color => 'yellow' },
  { :name => 'apple', :color => 'green' },
  { :name => 'orange', :color => 'orange' } 
]
table = Noguchi.table_for(fruits)

generates

namecolor
bananayellow
applegreen
orangeorange

Adding arbitrary custom-rendered columns

table = Noguchi.table_for(users)
table.add_field(:edit)
table.to_render_body_cell_for(:edit) do |context,cell|
  cell.raw_content = link_to( "Edit this user", edit_user_path(context.datum) )
end

generates

NameAgeSexEdit
Jenny24FEdit this user
Dave32MEdit this user
Hank27MEdit this user

The approach

I decided that since the goal of this library was to make table creation code look less ugly I would let the design of the API drive the process. So I started off by thinking about how I’d like table creation code to look like, basically just writing some rough ruby code that used the as-yet-unwritten library to render a basic table. The idea here was to get a simple core API which would render a basic table with very few lines of code, but to make the table rendering customizable by adding various tweaks to that basic table. Once I was happy with how the core API looked I started writing more complex examples, letting that drive out more advanced features in the API. These features were optional configurations which aimed to handle the most common kinds of customization I seem to end up doing to a table. Things like customizing a column header, adding an extra column to contain an edit link, things like that.

Once I had a rough idea of the API in my head, I started writing tests that described the functionality, implementing just enough of the library at each step to make the tests pass. I was plesantly surprised at how well this worked; the entire implementation was driven out by these tests. While I do tend to TDD most of the time, I’ve seldom done so exclusively. I tend to find myself spending some small amount of time outside of the Red-Green-Refactor loop, usually while exploring a new design approach or a brand new subsystem. I’m quite pleased with how this exclusively TDD approach played out in this case, although I wonder whether it would work quite as well in different circumstances.