about processes and engines

Archive for the ‘http’ Category

rufus-jig 1.0

By the end of 2007 I had written a gem sitting on top of net/http. It was called rufus-verbs, this extra layer added a mini cache for conditional GETs, basic auth and digest auth, cookie jar and more.

I used it for a while, I got surprised by people using it (IIRC the digest auth was their reason for using it). And then I forgot it.

Since last year, I am working with things like CouchDB and ruote-kit. I need an HTTP client that groks JSON. I still need it to understand conditional GETs (etags and co).

So I built rufus-jig, something on top of Ruby’s net/http, net-http-persistent, patron or em-http-request. It uses rufus-json to select the best JSON library available (in the order yajl-ruby, json, activesupport, json-pure).

A GET would look like :

require 'rubygems'

#require 'net/http/persistent'
  # http backend

require 'yajl' # gem install 'yajl-ruby'
  # json backend

require 'rufus/jig'

h ='')

p h.get('/users/jmettraux.json')['description']
  # => "another fool"

You specify the HTTP and the JSON backend before requiring rufus-jig and that’s it.

Rufus-jig comes with a class to deal with some of CouchDB specifics.

require 'net/http/persistent'
require 'yajl'
require 'rufus/jig'

c ='', 'rufus_jig_test')

# PUT and GET

c.put('_id' => 'coffee0', 'category' => 'espresso')
c.put('_id' => 'coffee1', 'category' => 'instantaneous')

coffee1 = c.get('coffee1')
coffee1['brand'] = 'nescafe'

# attaching

coffee0 = c.get('coffee0')

c.attach(coffee0, 'picture','espresso.jpg'), :content_type => 'image/jpeg')

# fetching all docs

p c.all
p c.all(:skip => 100, :limit => 100)

# fetching a batch of docs

p c.all(:keys => %w[ coffee0 coffee2 coffee7 ])

# querying views

p c.query('my_design_doc:my_view', :key => 'Costa Rica')
p c.query_for_docs('my_design_doc:my_view', :key => 'Colombia')

# bulk operations

docs = c.all(:keys => %w[ doc0 doc1 doc3 ])
c.bulk_delete(docs) # deleting in one go

docs = c.all(:keys => %w[ doc0 doc1 doc3 ])
docs.each { |doc| doc['status'] = 'copied' }
c.bulk_put(docs) # updating in one go

# ...

# listening to CouchDB activity

c.on_change do |doc_id, deleted|
  puts "doc #{doc_id} has been #{deleted ? 'deleted' : 'changed'}"

c.on_change do |doc_id, deleted, doc|
  puts "doc #{doc_id} has been #{deleted ? 'deleted' : 'changed'}"
  p doc


Rufus-jig just reached 1.0. I’ll probably go on with extending it. It’ll probably need digest authentication at some point, gzipping, why not. I’ll leave the CouchDB function in it for now. We’ll see.


source code :


Written by John Mettraux

December 8, 2010 at 6:28 am

Posted in couchdb, http, ruby, rufus