Quantcast
Channel: a little place of calm » couchdb
Viewing all articles
Browse latest Browse all 10

CouchDB on Rails (part 5 of ?)

$
0
0
  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://github.com/dchelimsky/rspec.git vendor/plugins/rspec
git submodule add git://github.com/dchelimsky/rspec-rails.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://github.com/paulcarey/relaxdb.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!

Configuration

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
end

Use script/console to ease us in gently

./script/console
Loading development environment (Rails 2.1.0)
>> cd = Cd.new
=> #
>> cd.title = 'Made Of Bricks'
=> "Made Of Bricks"
>> cd.save
=> #

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

[info] [] 127.0.0.1 - - "GET /cd_collection" 200
[info] [] 127.0.0.1 - - "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 = Cd.new(:title => "Delete me")
=> #
>> cd.save
=> #
>> RelaxDB.load("77d7a1f0-625b-012b-aeb4-001a9205e793")
=> #
>> cd.destroy!
=> #
>> RelaxDB.load("77d7a1f0-625b-012b-aeb4-001a9205e793")
RuntimeError: 404:Object Not Found
METHOD:GET
URI:/cd_collection/77d7a1f0-625b-012b-aeb4-001a9205e793
{"error":"not_found","reason":"deleted"}

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



Viewing all articles
Browse latest Browse all 10

Trending Articles