Find file
Fetching contributors…
Cannot retrieve contributors at this time
68 lines (50 sloc) 3.26 KB


by Matthew Lyon <>


A CouchDB ODM (Object/Document Mapper) in Ruby.


Encourages per-“Account” databases. Actually, does not even currently provide a way to do a “singleton” or global database, however this is planned. Since a given class (say, “Article”) cannot know what database it is supposed to get/search from you cannot do classical class-based finders such as “Article.find('value')”. While it might be possible to pass in a database to use for some class-wide view, Exegesis takes the opinion that this is bad design for couchdb for the reasons that views may return multiple document types other than the desired class, and that views should be scoped to objects that mixin the database accessors.

CouchDB is table-less, and Exegesis's design reflects this. In CouchDB, Documents are retrieved by their unique id, or can be queried from a view function in a design document. Exegesis provides tools to aid this. Additionally, since view functions can be used for map/reduce computations against your documents, Exegesis helps you get non-document data out of your views.


class Account
  include Exegesis::Database

  # declares the existence of a design document named 'articles'
  # view functions will be loaded from 'views/articles/:viewname/*.js
  design :articles do
    docs :by_author
    docs :at_path
    docs :tagged_with
    hash :tags_count, :view => :tagged_with

# performs GET '/_design/articles/_view/by_author?key="user-mattly"&include_docs=true&reduce=false'
# transforms the range into startkey/endkey
# performs GET '/_design/articles/_view/at_path?startkey="blog/2009"&endkey="blog/2009/04/04"
#               &include_docs=true&reduce=false'
# performs GET '/_design/articles/_view/tagged_with?key="couchdb"&group=true'

class Article
  include Exegesis::Document

  # defines readers, writers for given attributes
  expose :path, :title, :body, :tags
  expose :published_at, :writer => false, :as => Time

  # will load the document at the id referenced by doc['author']; does not yet set writer.
  expose :author, :as => :reference


  • RestClient 0.9 or later.

For running the tests:

  • MiniTest MiniTest is the default testing framework for Ruby 1.9 However, these tests require the trunk version, and my patches against the trunk version. The trunk version is here: My patches are in my fork: You will need to clone my repo and from its directory, do the following:

    `rake gem`
    `sudo gem install pkg/minitest-1.3.1`

    Once MiniTest 1.3.2 is released you should be able to use the standard gem.

The test suite creates and destroys a database for each test that requires access to the database. This is slow, and the test suite may take some time to run. However, I would rather the test suite be slow and accurate than quick and full of mocking or possibly error-prone deleting.