Monday, July 6, 2009

I <3 Haml and Prototyping Better CouchDB Design Document Support

‹prev | My Chain | next›

First up tonight, I take some time to split some Haml attributes into multiple lines. Back in my Perl days, I loved packing as much information onto a single line as possible—"look how much I can do with one line!"

Nowadays, I view long lines as an attempt to obfuscate complexity. Maybe that is what is really going on, maybe not (in my Perl days, that is certainly what I was doing). 60 characters long is my maximum. It discourages horizontal complexity.

Happily there are all sorts of things to split on in Ruby: the message send operator (i.e. "."), commas, boolean operators, etc. Frustratingly, I could use none of those techniques with my Haml code. Until today.

Well, I could have done so before today, I had known that Haml 2.2 let me split attribute lines. So the first thing that I do is update my Haml gem:
gem update haml
With that, I do a quick scan through each Haml template, updating appropriately:
...
%form{:action => "", :method => "get"}
%input{:name => "q",
:type => "text",
:tabindex => 1,
:maxlength => 2048,
:size => 15}
...
Ahhh.... much better.

I also spend some time today prototyping how I might break my CouchDB design documents into Javascript files that can be assembled into JSON documents based on the directory structure. If I have a file couch/_design/lucene/transform.js, I mean to be describing the lucene JSON document with a single attribute, "transform", that points to a value of the code in the file transform.js. More complex JSON structures would be possible with deeper directory structures.

I am still not certain that I want to do this, but the idea seems worth some investigation, so I prototype to learn.

I ultimately end up with this code that does the job:
  docs = { }
Dir["#{DESIGN_DOC_DIR}/**/*.js"].each do |filename|
path = File.dirname(filename).
gsub(/#{DESIGN_DOC_DIR}\//, '').
split(/\//)
path << File.basename(filename, ".js")

doc_name = path.shift

file = File.new(filename)
js = file.read

docs[doc_name] = { path.first => js }
end


docs.each do |document_name, doc|
RestClient.put "#{@@db}/_design/#{document_name}",
doc.to_json,
:content_type => 'application/json'
end
I am entirely unsatisfied with it. I should be relying on recursion to build up the data structure (this currently only works with a depth of a single directory) and it needs to build all documents in the docs local variable. Still, it works.

The main benefit that I could derive from the approach is being able to unit test my .js files while still retaining the ability to easily load the CouchDB design documents.

I think this is worth pursuing a bit more, so I will likely take a another day or two to prototype or implement.

No comments:

Post a Comment