As I have been experimenting with CouchDB replication, I have grown enamored of the idea of replicating application as well as data. Today, I will give couchapp a try. I am not set up for any kind of Python work, so first up I need to able to run Python easy_installs. On Ubuntu, I need to:
sudo apt-get install python-setuptoolsAfter that I can run
sudo easy_install couchapp
to install couchapp:cstrom@whitefall:~$ sudo easy_install couchappWith that, I can generate a "hello world" couchapp. Since this is CouchDB, I will call this "relax":
Searching for couchapp
Reading http://pypi.python.org/simple/couchapp/
Reading http://github.com/couchapp/couchapp/tree/master
Best match: Couchapp 0.5.3
Downloading http://pypi.python.org/packages/source/C/Couchapp/Couchapp-0.5.3.tar.gz#md5=ee1ba536818307041d4640d6168c0fd4
Processing Couchapp-0.5.3.tar.gz
Running Couchapp-0.5.3/setup.py -q bdist_egg --dist-dir /tmp/easy_install-OsHEBm/Couchapp-0.5.3/egg-dist-tmp-gPkP1h
zip_safe flag not set; analyzing archive contents...
couchapp.utils: module references __file__
couchapp.generator: module references __file__
couchappext.compress.yuicompressor: module references __file__
couchappext.compress.compress_css: module references __file__
Adding Couchapp 0.5.3 to easy-install.pth file
Installing couchapp script to /usr/local/bin
Installed /usr/local/lib/python2.6/dist-packages/Couchapp-0.5.3-py2.6.egg
Processing dependencies for couchapp
Finished processing dependencies for couchapp
cstrom@whitefall:~/repos$ couchapp generate relax && cd relaxIn that directory, I find:
cstrom@whitefall:~/repos/relax$ ls -FBut what goes into these directories?
_attachments/ couchapp.json _id lists/ shows/ updates/ vendor/ views/
After consulting the documentation a bit, I need to add anonymous javascript functions into these directories. The names of the files will become attributes on the constructed design document and, hence, part of the URL to be accessed. First up, I create an
shows/test.js
file that returns a static HTML string:function(req, doc) {Then I push this to the same database that contains all of my meals and recipes:
return "<h1>Testing</h1> <p>This is a test.</p>";
}
cstrom@whitefall:~/repos/relax$ couchapp push http://localhost:5984/eeeBefore checking on that URL, I first check my existing design documents. I have a lot of them upon which my Sinatra relies heavily so I'd be very put out if they were touched. Happily, they were not and I now have a shiny (and relaxing) new design document:
[INFO] Visit your CouchApp here:
http://localhost:5984/eee/_design/relax/index.html
There are no view functions (maps/reduces) as with the old meals and recipes design documents, but hopefully there is a show function with some very simplistic output:
With that working, what are the two parameters on the test.js function? The second one is the request object, which can be used to obtain query parameters:
function(doc, req) {When I access the page at
return "<h1>Testing</h1> <p>This is a test.</p>" +
"<p>query param foo=" + req.foo + "</p>";
}
http://localhost:5984/eee/_design/relax/_show/test?foo=bar
, I don't get a value of "bar" as I expected. Instead, I get undefined:I thought that would work. So if I can't get access to the query parameters directly on the request object passed into the anonymous function, how do I get access? Well, let's check the properties on the request object first:
function(doc, req) {This shows the following properties on the request object:
var keys = [];
for (var key in req) {
keys.push(key);
}
return "<h1>Testing</h1> <p>This is a test.</p>" +
"<p>query param foo=" + req.foo + "</p>" +
"<p>request object has:" + keys.join(', ') + "</p>";
}
Ah, there is a query property in there. Hopefully I can get the query parameter from that:
function(doc, req) {Yup, there it is:
var keys = [];
for (var key in req) {
keys.push(key);
}
return "<h1>Testing</h1> <p>This is a test.</p>" +
"<p>query param foo=" + req.query.foo + "</p>" +
"<p>request object has:" + keys.join(', ') + "</p>";
}
Cool. Well, that's the request object, what about the document object that is passed into the anonymous show function? To supply a particular document, the document ID needs to be passed at the end of the URL. To supply the test sequence document that I was using last night, the URL would be
http://localhost:5984/eee/_design/relax/_show/test/test-sequence?foo=bar
. As it is written right now, the show function is not actually doing anything with the document. To display the number attribute of the test-sequence document, I alter the show function:function(doc, req) {Now, accessing the URL shows the current sequence number:
var keys = [];
for (var key in req) {
keys.push(key);
}
return "<h1>Testing</h1> <p>This is a test.</p>" +
"<p>Current number is: " + doc.number + "</p>" +
"<p>query param foo=" + req.query.foo + "</p>" +
"<p>request object has:" + keys.join(', ') + "</p>";
}
That is pretty cool. Obviously, it would be a lot cooler if the show functions could display forms that could create and edit new CouchDB documents. This is just what couchapp promises. I will explore that more in a couple of days, but first...
I turn on my second machine et voilà:
The couchapp generated show document is automatically there.
Day #15
Thank you for writing this! I have been having some trouble getting started with CouchApp as docs can be sparse. I look forward to your future posts on the matter and can't wait to read more.
ReplyDeleteThe CouchDB book is a pretty good reference: http://books.couchdb.org/relax/ -- I'm relying on it and looking through the sofa code quite a bit trying to figure this out. That said, there's no substitution for actually doing it. I'm finding quite a large gap between what I think I know and what I really know when it comes time to writing this up!
ReplyDeleteThis has been great for my understanding and I'm thrilled someone else has found it useful :)