Posts Tagged ‘sor09’

New Couch Potato: simple, testable, opinionated.

Sunday, May 17th, 2009 by Alexander Lang

After my talk about Ruby CouchDB frameworks at Scotland on Rails where I dismissed a few of of the libraries available (including my own Couhch Potato) as not fitting the CouchDB way of doing things, I have been hacking away the past few weeks working on a complete overhaul of Couch Potato.

As a first result I have just released version 0.2 of the framework. Its new goals are simplicity, embracing the CouchDB semantics and testability. In order to achieve this I had to introduce some major changes:

I disconnected models from the database – there are no more save/get/find methods in the models. Instead you can hand the models to a database object that will save/load documents for you – this allows for unit tests that are completely disconnected from the database

I have dropped associations and thrown away all the ActiveRecord like view creation/querying, replacing it with a new, more CouchDB like system. That new system is lighter, simpler and easier to extend.

The following paragraphs will show you how to work with the new Couch Potato.

Saving / loading models

As I said I have decoupled the models from the database, a model doesn’t have permanent access to the database anymore. Instead you instantiate a database object yourself and tell it to load or save a model object. This change isn’t so much about CouchDB as it is about testability. Having the database separated means you can now have true unit test of your models without talking to the database. Here is how you save/load models:

class Book
include CouchPotato::Persistence
property :title
end

CouchPotato::Config.database_name = ‘my_db’ # in Rails this is done for you
db = CouchPotato.database

book = Book.new :title => ‘The Passionate Programmer’ # good book
db.save! book # saves the book or raises an exception

db.load book._id # the original book

The database is responsible for running the model’s validations and lifecycle callbacks, saving the document to the database and afterwards setting the _id and _rev on the model. This way a lot of the persistence related logic is removed from the models making them more lightweight and most importantly easier to test (see below).

New Views

Overhauling of the views had two main goals:

  • provide a simple and extensible way for saving/querying views that works the way CouchDB works
  • since models don’t have access to the database anymore, find a new way to query them

Here is how you create and query a simple view:

class Book
view :by_title, :key => :title
property :title
end

db = CouchPotato.database
db.view Book.by_title # no parametters
db.view Book.by_title(:key => ‘The Passionate Programmer’, :descending => true) # just use any of the parameters CouchDB accepts

The way views work is now essentially reversed (inversion of control, rings a bell?). Instead of the view method calling the database the new view method creates a specification for a CouchDB view. The view is passed to the actual database in order to query CouchDB. Again this makes testing easier (see next section) but it also gives Couch Potato a clean interface in order to make creating views easier through abstractions. There is now a hierarchy of view specification classes that you can use to more easily create and query views. The above example used the CouchPotato::View::ModelViewSpec which is the default. This spec creates a view whose map function emits one (or an array of) attribute of the model and returns full documents.

Other view specs let you create more customized views, for example the RawViewSpec, which lets you define your own map/reduce functions and return the raw CouchDB results hash.

class Book
view :title_length, :type => :raw, :map => “function(doc) emit(doc.title.length, null)}”
property :title
end

db.view Book.title_length # returns something like {:rows => [{:key => 25}]}

For more examples see the Documentation in the CouchPotato::View::*ViewSpec classes.

Testing

As I have mentioned repeatedly decoupling the database from the models makes testing easier. With the new Couch Potato you can unit test your models without hitting the database once. First of all that makes your test lightning fast, and secondly it allows you to more easily test for example your lifecycle callbacks because you can call them directly passing them a stub or mock database.

Here’s an example: (with RSpec)

class Book
property :title
property :slug
end

describe Book, ‘create’ do
it ’should generate a slug’ do
book = Book.new :title => ‘The Passionate Programmer’
book.run_callbacks :before_create
book.slug.should == ‘the-passionate-programmer’
end
end

If you don’t like calling the run_callbacks method you can also use the actual database object but without a real connection to CouchDB. Couch Potato is based on the excellent CouchRest – a more low level CouchDB framework. The CouchPotato::Database constructor expects an instance of a CouchRest database which we can replace with a stub:

describe Book, ‘create’ do
it ’should generate a slug’ do
book = Book.new :title => ‘The Passionate Programmer’
db = CouchPotato::Database.new stub(‘couchrest database’, :save_doc => {})
db.save book
book.slug.should == ‘the-passionate-programmer’
end
end

For more details and examples please see the README, the RDocs and watch this blog. If you want to know all about Couch Potato I encourage you to read through its source code and specs – it’s not that much code actually. Note that all this is still work in progress and time will show how well all of this works. I would be happy to hear your feedback.

The case of ActiveRecord vs. CouchDB

Tuesday, March 31st, 2009 by Alexander Lang

After my Ruby sittin’ on the Couch talk about Ruby Frameworks and CouchDB at Scotland on Rails last week a bit of a debate started. In the talk I did compare the available Ruby Frameworks and discussed how well they fit the CouchDB way of doing things. In my conclusion I recommended using either CouchRest or RelaxDB for development and at the same time urged people not to use one of the ActiveRecord like libraries like CouchFoo.

As it seems to me the intention of my talk hasn’t reached all of its audience yet I’ll try to make my point again using this blog post.

The frameworks I looked at could be divided into two classes: the ones using CouchDB semantics (e.g. CouchRest/RelaxDB) and the ones trying to provide an ActiveRecord like interface for the applications (e.g. CouchFoo). The reasons I recommended not to use ActiveRecord semantics are:

CouchDB is not about relations

In ActiveRecord we have to model our domain models so they fit into a relational schema. That means flat tables and relationships between two tables, through a third and fourth table etc. To get results from the database we usually join a few tables and get back the resulting rows, nicely converted into Ruby objects for us. That is (sort of) fine for a relational database because all it has are those tables but it doesn’t work at all with CouchDB.

To use CouchDB to its full potential you need to understand and use its views

CouchDB doesn’t have a concept of tables at all. And the way you pull your data from CouchDB is fundamentally different. Instead of joining data from different tables via an SQL query you procedurally build up an index of data by providing the map and reduce functions which you then query.

In order to fully use CouchDB you have to write custom map/reduce functions and abstracting that into an API that was designed for generating SQL queries doesn’t allow you that.

I could go into more details but that really is my main point. I know from my experience that changing the wiring in your head after too many years of ActiveRecord is hard so I don’t expect anyone to immediately agree with me but I do believe that the only viable way of using CouchDB is through the interface that was designed for it and not by an abstractions that just happened to be there first.

I’m looking forward to a lively discussion, either in the comments or on other blogs.