What do we have here?
It would seem to be yet another blog, and it is. This one, however, is built with merb and CouchDB so building it gave me a chance to experiment with some interesting projects that I don’t get to use in my daily life as a professional web developer.
The code for this site is available to the many-eyes beasts of the Interwebs here:
git://sprocket.slackworks.com/srv/git/blarg.git
It requires merb and friends, as well as an instance of CouchDB to be running somewhere. There are a few reasons I chose merb over Rails (which is what I generally use professionally) to do this:
- It comes with no pre-packaged ORM. I wanted to use CouchDB, so none of the existing ORMs would really work for me. My previous experiences of trying to rip ActiveRecord out of Rails have been frustrating.
- It has more flexible routing than Rails. I realize there are ways to accomplish the things I’m doing here in Rails, but the merb routes seem clearer to me, less hand-wavy. And perhaps most importantly:
- It’s not Rails. I use Rails all day long, and I wanted to see what else is out there.
Moving along. I’m using CouchObject to communicate between Ruby and CouchDB, but I found CouchObject’s Persistable API a little unsatisfying, so I wrapped in a class I’m calling CouchBase. Classes that extend CouchBase can define couch_accessor
s that are populated from, and saved to, CouchDB.
class Post < CouchBase couch_accessor :title, :summary, :body, :author, :tags, :created_at ... end
couch_accessor
is defined in CouchObject
as such:
def self.couch_accessor(*fields) meta_def(:couchables) { fields } end
This just takes note of which attributes should be saved in CouchDB because this can’t be inspected from a schema like with ActiveRecord. The method meta_def
is part of metaid. When any of these attributes is read from or written to, it’s actually the class’s @document
that is accessed.
def method_missing(meth, *attrs) field = meth.to_s.gsub('=', '') proxied_methods = self.class.couchables + [ :id, :new? ] if proxied_methods.include?(field.to_sym) @document.send(meth, *attrs) rescue nil else super end end
Then, if the object is save
-ed that @document
is written to CouchDB. Objects pulled from the DB via CouchObject#find_by_id
have their @document
populated from the CouchDB record.
One caveat I noticed using CouchObject: CouchDB expects temp view POSTs to have the mime-type “text/javascript” but CouchObject sends them as “application/json” so you have to add application/json=/usr/local/bin/couchjs -f /usr/local/share/couchdb/server/main.
js
to the end of your /usr/local/etc/couchdb/couch.ini
.
I’ll try to get comments working soon so people who want to blab may do so. In the mean time you can write to me at gnarg (at) slackworks.com and don’t forget to check out the code.