CouchDB on Rails (part 5 of ?)

  1. An introduction to CouchDB
  2. Installing CouchDB
  3. Experimenting with CouchDB’s web interface
  4. Integrating with Rails using ActiveCouch
  5. Integrating with Rails using RelaxDB
  6. Getting to scaffolding using RelaxDB
  7. Installing CouchDB from Subversion source code
  8. Trying out couchrest and topfunky’s basic_model

So today i’m going to try using the RelaxDB plugin. I am fortunate in that there is a tutorial already written, which might make it easier. However, the tutorial is for Merb, so it might not work at all on Rails. We’ll see.

Start a new Rails project

I have deleted my previous project and i’m starting again. The initial steps are the same as last time to create the project, create a Git repository, and bring in RSpec.

rails cd_collection
cd cd_collection
git init
git submodule add git:// vendor/plugins/rspec
git submodule add git:// vendor/plugins/rspec-rails
./script/generate rspec

I’m slightly confused as to whether you’re supposed to install RelaxDB as a gem, or whether it is okay just to include it as a plugin. For now i’m going to try as a plugin.

git submodule add git:// vendor/plugins/relaxdb

Spec tests

Like all good projects, RelaxDB has some RSpec tests, but before i can run them i need a few more gems such as extlib, json, uuid. Just use ‘gem install’ as root to install them. The specs will not run until you meet all the requirements.

I also found that the specs require CouchDB to be running on http://localhost:5984. As before, i use the su impersonate command to get it running.

sudo -i -u couchdb couchdb

And now for the moment of truth …

rake spec
Finished in 6.620036 seconds
114 examples, 0 failures

Amazing! I’m feeling very hopeful about this! So let’s jump straight in!


A big win over ActiveCouch, RelaxDB has the option to set the database connection details. First i have to require the RelaxDB plugin … i’m doing this in config/environment.rb

require File.join(File.dirname(__FILE__), '../vendor/plugins/relaxdb/lib/relaxdb')

I suspect if i’d installed it as a gem i would have been able to just do this:

require 'relaxdb'

Never mind. It’s fine. Now i can set my database connection details:

RelaxDB.configure(:host => 'localhost', :port => 5984)
RelaxDB.use_db 'cd_collection'

Create a model

The key thing today is to inherit from RelaxDB::Document. It seems i also have to set up the fields (in RelaxDB they are called properties). For now i’ll just start with a title.

# app/models/cd.rb
class Cd < RelaxDB::Document
  property :title

Use script/console to ease us in gently

Loading development environment (Rails 2.1.0)
>> cd =
=> #
>> cd.title = 'Made Of Bricks'
=> "Made Of Bricks"
=> #

It is my lucky day!! Let’s see if that actually did what i think it did. The CouchDB log file looks promising:

[info] [] - - "GET /cd_collection" 200
[info] [] - - "PUT /cd_collection/deadea40-6256-012b-aeb2-001a9205e793" 201

And yes, sure enough, here’s my new document sitting happily in the database:

A new CouchDB document created via RelaxDB

I notice the ‘class’ field has been inserted with the value ‘Cd’. This is clearly a special field that RelaxDB uses to map the document to a model in Rails. It’s a much better idea than ActiveCouch which seemed to want a separate database per model.

What else can we do? Find our CDs again? In ActiveRecord you’d do Cd.find(:all) but in RelaxDB it’s just Cd.all

>> Cd.all
=> [#]

I wonder if i can trick it into finding the other CDs in my database, if i add the ‘class’ field to them all …?

>> Cd.all
=> [#, #, #, #, #, #]

Sure enough, yes! It works! And look what else i’ve just seen:

RelaxDB made its own view

RelaxDB helpfully created the view that it needed to search for CDs. I am very impressed.

Searching by ID is slightly different from ActiveRecord. Instead of Cd.find(id) we need RelaxDB.load(id)

>> RelaxDB.load(1)
=> #

Oh, by the way, i added ‘artist’ as a property in the model. That works too! :)

Remember that most documents will be looked up using a UUID that RelaxDB will generate for us. That first CD just happened to be ID 1 because i gave it that ID the other day.

>> RelaxDB.load("deadea40-6256-012b-aeb2-001a9205e793")
=> #

There doesn’t seem to be a ‘find’ method. I don’t know how we would find the first CD, or search by title.

RelaxDB can delete documents using a ‘destroy!’ method:

>> cd = => "Delete me")
=> #
=> #
>> RelaxDB.load("77d7a1f0-625b-012b-aeb4-001a9205e793")
=> #
>> cd.destroy!
=> #
>> RelaxDB.load("77d7a1f0-625b-012b-aeb4-001a9205e793")
RuntimeError: 404:Object Not Found

Dead end

Unfortunately, i seem to have come to a dead end here. Although i think i have everything needed for some basic web app scaffolding, i keep getting the following error when i try to load a page in a web browser:

Rails error when trying to connect to CouchDB

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.reverse

This happens even if i have a completely empty action in the controller.

The error seems to be coming from ActiveRecord, so i think something is still calling ActiveRecord when it shouldn’t. Anyone got any ideas? Why would it even bother to load ActiveRecord when the model inherits from RelaxDB?

Anyway, i’m not finished with RelaxDB yet. I like what i’ve seen so far. I’ll publish this progress and hope to get some feedback on the error. My next post will hopefully be a tutorial about creating the Rails scaffold.

Edit to add: The problem comes when i include relaxdb in the environment.rb. Is there a way to get around this?

Edit again to add: It does seem to work if i put the include statement into the application controller. I think i’m back on track. Stay tuned for the next installment!

Part 6: Getting to scaffolding using RelaxDB


13 comments on “CouchDB on Rails (part 5 of ?)

  1. It’s interesting to see how RelaxDB builds on CouchDB. Since CouchDB is so simple, there are many ways to use it, and it’s nice to have a library like RelaxDB that provides an example of one way to use it. It looks like RelaxDB makes it easier for people who are used to thinking in terms of tables to begin using CouchDB.

    Nice article. I like how you show every step you take, because I can pick up on little unrelated bits of information (like the “-i” option that can be passed to sudo). It feels like I’m watching a screencast, except I can learn at my own pace and headphones aren’t required.

  2. It’s really helpful to see the contrast between these frameworks. I’m beginning to think about how best to layer an application-model style wrapper on top of CouchRest. It’s good to see what’s helpful and what gets in the way, or is missing from these other libraries. Keep up the good work, looking forward to what’s next!

  3. @Ben, thank you for your encouragement.

    @Chris, i think the most important and useful feature would be to make use of CouchDB’s dynamic document structure. If you can make a library that doesn’t try to apologise for CouchDB’s lack of schema, that would be awesome! :) I think the ability to create its own views when it needs them is a very strong feature.

  4. If you are having problems running the spec, you might need to update your gems.

    This is the error I was getting:

    undefined method `generate’ for “0322b6d0-6270-012b-24ea-0017f2d556c5”:String

  5. Hi Aimee. First of all congratulations on your blog. I’m learning a lot.
    Now I need some help with running the rspec in my project.
    I’m getting the error:
    rake aborted!
    #42000Unknown database ‘sysx_development’
    when i run “rake rspec”. This is the database that is in my database.yml file and is setted to mysql. I tried to configure the file like this:
    adapter: couchdb
    database: sysx_development
    port: 5984
    After that, executing rspec asks for a gem called activerecord-couchdb-adapter. But it doesn’t exist. Am I going throw the wrong way?

  6. Hi Bruno,

    I don’t think you can use database.yml together with CouchDB. There is no couchdb adapter that i know of.

    If you’re using RelaxDB you could try putting the details into your config/environment.rb:

    RelaxDB.configure(:host => 'localhost', :port => 5984)
    RelaxDB.use_db 'sysx_development'

    I can’t remember whether i maybe had to create an empty MySQL database just so that the database.yml didn’t cry.

  7. Hi Aimee,
    I configured the app like you sad. But when rails initialize it keeps calling the database.yml. I tried to turn off in enviroment.rb:
    config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
    There’s a bug in rails that it doens’t work very well. I think I’m missing something here. Do you have your source code anywhere so I can look at it?

  8. Great writeup! Aimee – I agree, that setting the properties explicitly is a pain.

    I would imagine that creating a view explicitly in CouchDB would let you do a search by title – sort of like creating a stored procedure (but I haven’t read parts 6+ yet, so maybe I’m jumping the gun!) Not Rails-y, but it’s not designed for Rails…

  9. A few things: I think you now have to specify a design_doc in RelaxDB.configure such as: RelaxDB.configure :host => “localhost”, :port => 5984, :design_doc => “app”also you may have to do rake db:migratejust to create a db/schema.rb, even if you are not using sqlite before you do rake spec

  10. Like all good projects, RelaxDB has some RSpec tests, but before i can run them i need a few more gems such as extlib, json, uuid. Just use 'gem install' as root to install them. The specs will not run until you meet all the requirements.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s