Cushion: A slim CouchDB client
Cushion is a Ruby client for accessing CouchDB servers that’s light on the extras and heavy on the syntatical sugar.
Credit goes to CouchRest (github.com/jchris/couchrest/tree/master) for the inspiration.
Getting Started
# myapp.rb
require 'cushion'
db = Cushion!(mydb)
Document Basics
Storing documents is simple. Just supply a hash of attributes. Leave out the _id attribute if you want to use an auto-generated UUID. Set the _rev attribute to update a document:
db.store("baz" => "bat")
# => {"ok"=>true, "id"=> "bdd39a3f9a1e5894d3d1283aa0d0f53f", "rev"=> "2699240268"}
response = db.store("_id" => "mydoc", "foo" => "bar")
# => {"ok"=>true, "id"=>"mydoc", "rev"=>"882534292"}
db.store("_id" => "mydoc", "foo" => "baz", "_rev" => response['rev'])
# => {"ok"=>true, "id"=>"mydoc", "rev"=>"3617508982"}
Fetching documents is just as simple.
db.key?("mydoc") # => true
db.fetch("mydoc") # => {"_id"=>"mydoc", "_rev"=>"3617508982", "foo"=>"baz"}
db.fetch("bogusid") # => raises RestClient::ResourceNotFound
# Use etags to perform a conditional GET
db.fetch("mydoc", :etag => cur_rev) # => raises RestClient::NotModified
Store attachments inline or via CouchDB’s standalone attachment API. The standalone method accepts both IO objects and strings:
# Inline
db.store("_id" => "hasfiles", ..., "_attachments" => {
"foo.txt" => {
"content_type" => "text/plain",
"data" => "Hello World!"
}})
# Standalone
res = @db.store("_id" => "savemefirst", ...)
db.attach("savemefirst", "foo.txt", "Hello World!", :rev => res['rev'],
:content_type => "text/plain")
# => Foo now contains an attachment hash similar to the above example
# Fetch attachment data
db.fetch("savemefirst", "foo.txt") # => "Hello World!"
Cushion returns parsed JSON by default. In those cases where you need the raw JSON string, simply set an accept header:
db.fetch("mydoc", :headers => { :accept => "text/plain" })
# => "{\"_id\":\"mydoc\",\"_rev\":\"3617508982\",\"foo\":\"baz\"}\n"
The technique above works for nearly every Cushion request method.
Document Macros
You can use CouchDB’s bulk docs feature to create, update and delete many documents at once:
docs = [
{ "_id" => "0", "_rev" => "123456", "_deleted" => true }, #=> Delete
{ "_id" => "1", "_rev" => "32486671", "foo" => "bar" }, #=> Update
{ "_id" => "2", "baz" => "bat" } #=> Create
]
db.bulk(docs) # => returns a hash of updated documents
db.bulk(docs, :delete => true) # => deletes the selected docs
Documents and attachments may also be copied or moved within the same database. Some useful examples:
# Documents
db.copy("mydoc", "new_doc")
# => {"ok"=>true, "id"=>"new_doc", "rev"=> ...}
db.move("mydoc", "existing_doc", :rev => ..., :dest_rev => ...)
# => overwrites the existing doc
# Attachments
db.copy_attachment("mydoc", "foo.txt", "bar.txt")
# => copies an attachment within the same doc
db.move_attachment("mydoc", "foo.txt", "bar.txt")
# => renames an attachment; aliased at #rename_attachment
See the database specs for more copy and move examples.
Views
-
creating (design docs)
-
querying
-
temp views
Servers and Databases
The server location defaults to 127.0.0.1:5984, so you may omit the host when initializing a server if you are satisfied with the default.
NOTE: Some cruft needs cleaning up. Use Cushion!(dbname, opts) for now.
Display various bits of server metadata as follows:
server.info #=> welcome message
server.all_dbs #=> all dbs available
server.active_tasks #=> running tasks (e.g., replication or compaction)
server.config #=> server config
server.restart #=> restart the server
server.stats #=> detailed runtime stats
Cushion::Server can also replicate local and remote databases:
server.replicate("db1", "db2")
server.replicate("db1", "http://host2:5984/bar")
Creating database instances:
-
top level methods
-
options
DB Operations:
db.create
db.delete
db.compact
Cushion::Document
Tricks
Use the #headers method to obtain response headers on any request:
db.fetch("mydoc").headers
# => {:server=>"CouchDB/0.9.0a (Erlang OTP/R12B)", :etag=>"\"3617508982\"",
:date=>"Fri, 06 Mar 2009 10:21:59 GMT", :content_type=>"application/json",
:content_length=>"48", :cache_control=>"must-revalidate"}