I’ve been playing around with and kicking the tyres of CouchDB for a couple of weeks and I’m truly excited about the project. If I was to use tags to describe CouchDB I’d use the following:
apache, opensource, documents, metadata, database, json, javascript, REST, addressability, horizontal scaling, erlang.
So I found myself at Railscamp UK on the weekend without a ruby+rails topic to really talk about during the presentations part of the camp. I’m still a noob wrt. Rails, you see. Realising that CouchDB is relevant to most web developers because most developers deal with document-based content at some point and that Ruby, Rails, and Erlang are kindda like the current bratpack (in a John Hughes-sense) of computer languages, I thought it would be a great little topic for a 15-minute presentation.
So I thought I share the slides and some of the code I hacked up on the weekend. First of all the slides…
You can play about with some sample code that was expanded upon after the presentation. Here’s a little helper class to interface into CouchDB using JSON and HTTP:
require 'rubygems'
require 'httparty'
require 'json/pure'
require 'find'
class CouchHack
include HTTParty
base_uri 'http://127.0.0.1:5984'
format :json
def update( path, document )
options = { :body => JSON.generate(document) }
puts self.class.put(path, options )
end
def get(path)
self.class.get(path)
end
def create(db_path, document )
options = { :body => JSON.generate(document) }
self.class.post(db_path, options )
end
def define_view(db_path, design_doc_name, views )
document = { "views" => views }
options = { :body => JSON.generate(document) }
self.class.put("#{db_path}/_design/#{design_doc_name}", options)
end
end
Once that’s in place you can use the CouchHack class by defining a view like so:
ch = CouchHack.new
gem_views = {
"small_gems" =>
{
"map" => "function(doc) { if (doc.length < 3000) emit(doc.path, doc) }",
},
"large_gems" =>
{
"map" => "function(doc) { if (doc.length > 3000) emit(doc.path, doc) }",
}
}
ch.define_view("/railscamp", "gems", gem_views)
This design document, as is its known in CouchDB parleance, defines two views (think ‘baked queries’), to return a list of small gems – those less than 3000 bytes – and a list of large gems – those larger than 3000 bytes.
So where do these gems come from and how do they end up in CouchDB ? That’s what the next and last little fragment of Ruby code does.
Find.find('/Library/Ruby/Gems/1.8/gems/' ) do |f|
if File.file?(f) and f.ends_with?('.rb' )
begin
gem_contents = IO.read(f)
gem_document = { "path" => f, "length" => gem_contents.length, "content" => gem_contents }
ch.create( "/railscamp", gem_document )
rescue Exception => bang
puts "Skipping #{f}"
end
end
end
So what happens is that the last little fragment traverses the filesystem starting at /Library/Ruby/Gems/1.8/gems/ and looks for *.rb files. When it finds one it POSTs that whole document including the file length to CouchDB, where it becomes part of the resultset of one of the pre-defined views. These views can be accessed through the following two URLs (assuming the ‘railscamp’ DB was used).
- http://localhost:5984/railscamp/_view/gems/large_gems
- http://localhost:5984/railscamp/_view/gems/small_gems
Feel free to post comments and ask questions.
Enjoy.
P.S. and if you get a chance to go to a *camp conference, GO! They’re an amazing format and you’ll learn soooo much!.
