CouchDB Backend for Hx
Just for grins I had a go at implementing a CouchDB backend for Hx today. It’s pretty straightforward; the document id in couch becomes the entry path in Hx, and the actual entry Hash is taken directly from the document JSON. Configuration of a CouchDB source is also quite simple:
filter: Hx::Backend::CouchDB
options:
couchdb_server: http://localhost:5984/
couchdb_database: entries
The filter options could actually be omitted entirely in this case, since the example represents the defaults if the server and database options aren’t given explicitly.
Here’s a stripped-down version of the CouchDB backend to demonstrate what an Hx backend looks like:
class Hx::Backend::CouchDB
include Hx::Source
def initialize(source, options)
@couchdb_server = options[:couchdb_server] ||
"http://localhost:5984"
@couchdb_database = options[:couchdb_database] ||
"entries"
end
def edit_entry(path, prototype=nil)
begin
text = get_document(path)
rescue HTTPError => e
raise e unless e.code == 404
raise Hx::NoSuchEntryError, path unless prototype
text = prototype.to_json
end
text = yield text
entry = JSON.parse(text)
entry['updated'] = Time.now.xmlschema
entry['created'] ||= entry['updated']
put_document(path, entry.to_json)
self
end
def each_entry
listing = JSON.parse(get_document('_all_docs'))
for row in listing['rows']
path = row['id']
entry = JSON.parse(get_document(path))
for field in %(created updated)
entry[field] = Time.parse(entry[field] || "")
end
yield path, entry
end
self
end
def get_document(id)
# ...
end
def put_document(id, body)
# ...
end
end
Some error handling has been removed, and I’ve elided the definitions
of get_document and put_document for the
sake of space. The main points of interest are:
CouchDB.new, which takes an upstream source (ignored by most backend sources) and an options hashCouchDB#edit_entry, which passes the raw (backend-dependent) entry text to its block, and replaces the entry in the database with the returned result, updating the'updated'and'created'fields.CouchDB#each_entry, which iterates through all the entries provided by this backend instance, yieldingpath, entrypairs. In Hx, entries are just Ruby hashes, nothing more.
Those three methods are really all any Hx backend needs to provide.