Monday, April 19, 2010

CoffeeScript

‹prev | My Chain | next›

I have been hearing much good about Coffeescript, so this seems a nice time to give it a try. To tie it (if only very weakly) to my chain, I will experiment with writing CouchDB design documents in coffeescript.

First up, downloading and installing the latest node.js and coffescript:
cstrom@whitefall:~/src$ tar zxvf ../Downloads/node-v0.1.91.tar.gz 
...
cstrom@whitefall:~/src$ cd node-v0.1.91/
cstrom@whitefall:~/src/node-v0.1.91$ ./configure --prefix=/home/cstrom/local
...
'configure' finished successfully (8.992s)
Fortunately, I have done this before, so I already have my dependencies satisfied. So I install to my local directory:
* installing build/default/node as /home/cstrom/local/bin/node
* installing build/default/src/node_version.h as /home/cstrom/local/include/node/node_version.h
Waf: Leaving directory `/home/cstrom/src/node-v0.1.91/build'
'install' finished successfully (10m44.412s)
And, simple as that, I have node.js 0.1.91 installed:
cstrom@whitefall:~/src/node-v0.1.91$ which node
/home/cstrom/bin/node
cstrom@whitefall:~/src/node-v0.1.91$ node --version
0.1.91
Now onto coffeescript, which I have already downloaded from the website. I untar it, then install it into my local directory:
cstrom@whitefall:~/src$ tar zxvf ../Downloads/jashkenas-coffee-script-92540d5.tar.gz 
cstrom@whitefall:~/src$ cd jashkenas-coffee-script-92540d5
cstrom@whitefall:~/src/jashkenas-coffee-script-92540d5$ ./bin/cake install -p /home/cstrom/local
Again, simply enough, I have the latest version of coffescript installed.

I write and maintain my design documents with couch_docs. If I am going to write my design documents in coffeescript, I need to make a couple of minor changes to the CouchDocs::DesignDirectory class, which is responsible for assembling design documents from the filesystem and loading them into the CouchDB database. After changing the class to look for .coffee scripts, I tell it how to read from the file system with coffeescript:
    def read_value(filename)
`cat #{filename} | coffee -sp --no-wrap`
end
I pipe the contents of the current coffee file into the coffee script. The -s option reads from STDIN rather than from a file. The -p option dumps the output to STDOUT rather than a file. The --no-wrap option instructs coffescript to omit the anonymous function wrapper that it normally uses (I am not positive that I needed this, but leave it for my playing).

One of my views collates meal documents by date:
function (doc) {
if (doc['type'] == 'Meal' && doc['published']) {
emit(doc['date'], doc);
}
}
In coffeescript form, I write:
(doc) ->
if doc['type'] == 'Meal' and doc['published']
emit(doc['date'], doc)
To use this with couch_docs, I create the usual directory structure and dump the coffeescript into it:
cstrom@whitefall:~/tmp/coffee$ find
.
./_design
./_design/meals
./_design/meals/views
./_design/meals/views/coffee_date
./_design/meals/views/coffee_date/map.coffee
cstrom@whitefall:~/tmp/coffee$ cat ./_design/meals/views/coffee_date/map.coffee
(doc) ->
if doc['type'] == 'Meal' and doc['published']
emit(doc['date'], doc)
Now, to see if this actually works. I upload this design document:
cstrom@whitefall:~/repos/couch_docs$ ./bin/couch-docs push \
http://localhost:5984/seed \
/home/cstrom/tmp/coffee
Updating documents on CouchDB Server...
And then try to use it:
cstrom@whitefall:~/repos/couch_docs$ curl http://localhost:5984/seed/_design/meals/_view/coffee_date
{"total_rows":1,"offset":0,"rows":[
{"id":"2002-08-26","key":"2002-08-26","value":{"_id":"2002-08-26","_rev":"5-f49a56547705fe4969afe60b19db7ea3","title":"Grilled Chicken and Pesto Pasta","published":true,"date":"2002-08-26","type":"Meal","serves":4,"summary":"..."}}}}
]}
Well how about that? It actually worked!

I do not know that I will end up making use of this (or even incorporating it into couch_docs officially). Still it was a fine excuse to experiment with coffeescript and a definite proof of concept.

Day #78

No comments:

Post a Comment