CouchRest: CouchDB, Close to the Metal
I have been contemplating the use of document-stores in my Ruby apps for a few months (you might remember my MongoMapper post from back in June), and I've been following developments in the No-SQL movement. George Palmer's presentation at Rails Underground on his couch_foo gem inspired me to explore the possibilities further, and I've recently started work on incorporating CouchDB into some projects that I'm working on.
What is a "document store?"
Couch is one of several available document oriented databases (the other main contender being MongoDB, for which there's a good comparison on the Mongo website). Document stores go some way to bridging the gap between traditional functionality-rich relational databases (like MySQL, Postgres) and fast, highly scalable key/value stores (such as Toyko Cabinet). I think I should make it clear at this point that I'm not a SQL-hater: I worked as a DBA for a while a few years ago, and if you have truly relational data with a fixed schema and complex transaction requirements then you can't beat a good RDBMS.
With CouchDB and friends, data is held in documents. These documents don't have a fixed schema - they can have any number of arbitrary properties. This makes document stores great for holding collections of similarly (but not identically) stuctured items. CouchDB stores the data as JSON hashes, and provides a REST interface for creating, updating and querying.
Using CouchDB in your Ruby App
I've already mentioned couch_foo as one option for interacting with a CouchDB from Ruby app but after a bit of investigation, I eventually decided against it. Although it provides a familiar ActiveRecord-style interface and seems well-written, I wanted something that was a bit closer to couch's RESTful HTTP and JSON interface. Also, I wasn't convinced that extending the ActiveRecord paradigm to a document-based database was a good fit. I also dabbled with Alex Lang's couch_potato library, but finally decided on CouchRest.
CouchRest lightly wraps CouchDB's HTTP API (via RestClient, Heroku's Ruby HTTP wrapper), and provides a simple, Object-Mapper agnostic framework on which to build your application. Things just work as you'd expect: the JSON that comes back from CouchDB queries are presented as objects based on Ruby Hashes.
Models, Properties and Views
With CouchRest, you can define models for documents that share similar structures, deriving from
CouchRest::ExtendedDocument. Properties that are common to each Model can be declared with CouchRest's
property method. It also supports the automatic setting of created_at and updated_at properties, callbacks and validations.
class Article < CouchRest::ExtendedDocument include CouchRest::Validation property :date property :title property :slug view_by :slug validates_present :title timestamps! save_callback :before, :generate_slug_from_title def generate_slug_from_title self.slug = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^-|-$/,'') if new? end end
Hopefully this has given you a taster of what CouchDB might be good for, and how CouchRest can help you with integrating it into your Ruby app. Obviously there's much more too it than I've covered here, but this (draft) online O'Reilly book is a great place to start learning about CouchDB ...and it's co-written by J. Chris Anderson, author of the CouchRest Ruby library.