CouchDB on Rails (part 6 of ?)
- An introduction to CouchDB
- Installing CouchDB
- Experimenting with CouchDB's web interface
- Integrating with Rails using ActiveCouch
- Integrating with Rails using RelaxDB
- Getting to scaffolding using RelaxDB
- Installing CouchDB from Subversion source code
- Trying out couchrest and topfunky’s basic_model
Okay, after my brief disappointment earlier, i've found a way that seems to work, at least for the time being. I have taken the RelaxDB lines out of environment.rb and put them into the application controller instead.
# app/controllers/application.rb class ApplicationController < ActionController::Base require File.join(File.dirname(__FILE__), '../../vendor/plugins/relaxdb/lib/relaxdb') RelaxDB.configure(:host => 'localhost', :port => 5984) RelaxDB.use_db('cd_collection') end
Oh, i should say, i'm going to add the RESTful resources command into config/routes.rb:
map.resources :cds
I have also added some of the other properties into the model:
class Cd < RelaxDB::Document property :title property :artist property :publisher property :year_of_release end
It's a shame i have to do this. I'd like to see a wrapper for CouchDB which doesn't try to force a schema upon the database. That is one of CouchDB's biggest strengths - that documents can contain any fields you wish.
Index of all CDs
I know my boss will probably read this, so i'll do the right thing and start with a spec!
# spec/controllers/cds_controller_spec.rb describe CdsController do describe "index" do it "should look up all CDs in the database" do Cd.should_receive(:all).and_return([:some_cds]) get :index assigns[:cds].should == [:some_cds] end end end
And the code to make this pass is simply going to be:
# app/controllers/cds_controller.rb class CdsController < ApplicationController def index @cds = Cd.all end end
The spec passes. Let's write the view! Because RelaxDB wraps up the database so nicely for us, there is nothing unusual here at all.
<!-- app/views/cds/index.html.erb --> <h1>My extensive CD collection</h1> <table> <tr> <th>Title</th> <th>Artist</th> <th>Publisher</th> <th>Year of release</th> </tr> <% @cds.each do |cd| -%> <tr> <td><%= h(cd.title) %></td> <td><%= h(cd.artist) %></td> <td><%= h(cd.publisher) %></td> <td><%= cd.year_of_release.to_s %></td> </tr> <% end -%> </table>
Now we are definitely getting somewhere! :) But the CDs appear in the order they were created. To order them by artist then title, we can do this:
@cds = Cd.all.sorted_by(:artist, :title)
You know what RelaxDB is going to do now?
[info] [<0.2122.0>] 127.0.0.1 - - "GET /cd_collection/_view/Cd/all_sorted_by_artist_and_title" 200
Yep, it dynamically creates the views it needs. Clever, hey?! And here's the output:
Differences between ActiveRecord and RelaxDB
I'm not going to go through every line of code, but here are the main differences from ActiveRecord:
To find all CDs (as i already demonstrated):
# @cds = Cd.find(:all, :order => "artist, title") @cds = Cd.all.sorted_by(:artist, :title)
To find a CD from the parameters:
# @cd = Cd.find(params[:id]) @cd = RelaxDB.load(params[:id])
Updating attributes - there is no method 'update_attributes'. There is 'set_attributes' but it doesn't actually save the document - you have to do that yourself.
# @cd.update_attributes(params[:cd]) @cd.set_attributes(params[:cd]) @cd.save
Destroy requires an exclamation mark.
# @cd.destroy @cd.destroy!
Validations are rubbish. I managed to get it sort of working like this:
property :title, :validator => lambda {|t| t != ""}, :validation_msg => "cannot be blank" property :year_of_release, :validator => lambda {|p| p.to_i > 0}, :validation_msg => "must be a number"
And then in the view you have to do something like this:
<% @cd.errors.each_pair do |field, message| -%> <p><%= field.to_s.humanize %> <%= message %></p> <% end -%>
… it's very flaky though. Sometimes it lets it through even when the validation blatantly fails. Still, it's a known limitation.
My verdict on RelaxDB
I like it. I am glad that i had to change very little in the views to get it to work, and relatively few things in the controller. Apart from the validation and error messages, it's a good little plugin if you want to get going quickly on CouchDB. I'd like to see it allow dynamic fields on documents … that would be a good improvement.
I may work a bit more with RelaxDB … it would be good to find out how to link two models. Watch this space! :)
Part 7: Installing CouchDB from Subversion source code
Related posts (automatically calculated)


Add New Comment
Viewing 10 Comments
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Add New Comment
Trackbacks
(Trackback URL)