Johan Sørensen

CouchDb views in Ruby instead of Javascript

I’ve just pushed CouchObject 0.5 out to the rubyforge mirrors, here’s the History.txt file:

== 0.5.0 2007-09-15

* 2 major enhancements:
  * Database.filter{|doc| } for filtering the on doc, in Ruby!
  * couch_ruby_view_requestor, a JsServer client for CouchDb allowing you to query in Ruby

* 1 minor enhancement:
  * Added Database#store(document), the parallel of Document#save(database)

Those two major enhancements are a result of my laziness as reported at the end of the last post, because now you can query your CouchDb views in Ruby instead of Javascript:


$ irb -rubygems
>> require 'couch_object'
=> true
>> db = CouchObject::Database.open "http://localhost:8888/foo"
=> #
>> pp db.post("_temp_view", "proc{ |doc| return doc if doc[\"foo\"] =~ /qux/  }")
#
    [{"_rev"=>189832163,
      "_id"=>"96193CD461168BD024B64EA367C1E0BF",
      "value"=>
       {"_id"=>"96193CD461168BD024B64EA367C1E0BF",
        "_rev"=>189832163,
        "foo"=>"qux"}}],
   "offset"=>0,
   "total_rows"=>1,
   "view"=>"_temp_view:proc{ |doc| return doc if doc[\"foo\"] =~ /qux/  }"},
 @response=#>

Boom. The rows key there is our matching document with an attribute of foo that matches /qux/.
You just pass in anything that responds to a #call(the_couch_document) when you define your view request.

But passing around strings will make your eyes sore, so, lets just do this in pure Ruby:


>> pp db.filter{ |doc| return doc if doc["foo"] == "qux" }
[{"_rev"=>189832163,
  "_id"=>"96193CD461168BD024B64EA367C1E0BF",
  "value"=>
   {"_id"=>"96193CD461168BD024B64EA367C1E0BF",
    "_rev"=>189832163,
    "foo"=>"qux"}}]

Thanks to a bit of RubyToRuby we can send along the block to CouchDb just fine.
But, how is this all done on the CouchDb side of things? It’s actually a whole lot easier than it looks; all CouchDb does when it receives a view query like the above is pass it on to whatever is defined as the JsServer in $COUCH_INSTALL/couch.ini, this is normally SpiderMonkey, but with the CouchObject gem installed it can be Ruby!

Here’s the relevant section from my couch.ini:

  1. You need full, or relative to couch install dir, paths for now
    JsServer=/opt/local/bin/couch_ruby_view_requestor

So have a go at it:

  $ sudo gem install couchobject

Check out the Git source and have a play with it:

  $ git clone git://gitorious.org/projects/couchobject/mainline.git

Comments:

  1. james Says:


    Looks like the .ini file has changed format since you wrote this; it’s now reading like this (on my system)

    [Couch Query Servers]

    text/javascript=/opt/local/share/couchdb/server/couchjs -f main.js

    Thanks for your work on this. Makes it easier to play around and kick the wheels. I’m currently deciding whether to commit to couch for a big project and your plugin has helped get my head around things …

  2. johan Says:


    yeah, I need to bring it up to date with the latest couch trunk, I’ve been busy with other things for the past two weeks. The good news is that it’s now possible to use several view servers at once, so you don’t have to be “locked in” to just using ruby, or any other language, only.

  3. Matthew King Says:


    The new syntax for adding a query server to couch.ini is this:

    text/ruby=/wherever/couchobject/bin/couch_ruby_view_requestor

    The ruby query server is, as Johan says, out of date. I just submitted a patch on Rubyforge that fixes the one minor change in couch_ruby_view_requestor, updates the Ruby proc for the example view, and revises the specs and code where necessary to conform to the way CouchDB currently processes view.

    I just realized that I forgot to update the README. Johan, I’m using git, but I’m not very familiar with shared development practices. I can make my changes available in a public git repo, if that is helpful to you.