Ruby & Couch

It’s a long weekend this week in the UK. I wanted to learn a bit more Ruby, so I decided to use the time to start writing a client library for CouchDB. Basically my day job at Cloudant, but in Ruby.

I first used Ruby back in about 2005, and this site was powered by a couple of Ruby incarnations: first a Ruby on Rails app for a time; then a fairly hokey static site generator. I think that lasted until around 2009 when I learned Python and switched to Google AppEngine. Even with this experience, I don’t know Ruby particularly well – I have never used it full time – but I think the library has come out okay so far.

The client is is fairly low-level, which is my preference for clients, though not everyone’s. One sets up a client, then makes requests with it. Each type of request – GET _all_docs, PUT /database/document and so on – is represented by its own class, an idea Soroush Khanlou calls templating. We also used this approach for Cloudant’s Objective-C client library and it seemed a good approach; this Ruby library extends on lessons learned there.

require 'rubycouch'

client = CouchClient.new(URI.parse('http://localhost:5984'))
response = client.make_request(AllDbs.new)
response.json
# => ["_replicator","_users","animaldb",...]

It’s got some neat features. Most things can be streamed rather than read into memory. I tried to pick something useful for each request, but aside from views, I ended up just providing the option to stream the data to a block.

However, some are a bit cleverer. I like the views implementation which sends each result to a block:

get_view = GetView.new('views101', 'latin_name')
client.database('animaldb').make_request(get_view) do |row, idx|
  # => 0: {"id"=>"kookaburra", "key"=>"Dacelo novaeguineae", "value"=>19}
  # and so on. `row` is always decoded JSON. idx just tends to be useful.
end.json
# => {"total_rows"=>5, "offset"=>0,"rows"=>[]}

I certainly learned a lot about Ruby writing this. Right now the library is pretty incomplete in terms of API coverage, but is quite usable for simple projects – and importantly should be easy to add and contribute to. Perhaps I’ll be able to take the time to polish it up. I hope I can. Meanwhile, it should be fairly simple to get to grips with if you want to try it.

Find it on GitHub.

.:.