Easy document revisions with RelaxDB
I’ve been using CouchDB/RelaxDB for a project I’m working on, and I wanted an easy way to access CouchDB’s document versioning for my models. Here’s what I came up with.
Without going into too much detail, CouchDB doesn’t update documents in place, instead it creates a new document with the same ID and a new revision string. This gives you access to a rudimentary versioning system (which they warn you not to rely on, BTW.)
This functionality is perfect for the project I’m working on, which runs some tests at a regular interval and stores the results in CouchDB. I can then generate nice graphs based on the history of each object, so i can see how these test results have changed over time.
I messed with RelaxDB for Ruby for a little while to get this whole revisiony thing to work. For those familiar with RelaxDB, it exposes RelaxDB.load(_id, :revs=>true) for you, but due to limitations in Couch, you can’t get the :revs from a view, only directly loading an object. So to get around this, I mixed a revisions method into the Document class:
$YOUR_PROJECT/relaxdb/revisions.rb:
module RelaxDB
class Document
property :_revisions
property :_revs_info
def revisions(params={})
RelaxDB.load(self._id,:revs_info=>true)._revs_info.collect do |rev|
RelaxDB.load(self._id, :rev=>rev['rev']) if rev['status'] == 'available'
end
end
end
end
Now, inside of your models.rb, you can just include it:
$YOUR_PROJECT/models.rb:require 'relaxdb' require 'relaxdb/revisions' class MyModel < RelaxDB::Document property :name property :description view_by :name end
And then you can simply do this:
>> mm = MyModel.new(:name=>'Thing One') => #<MyModel:2165734660, _id: "96579a10-f749-012c-7654-001b63ac5fc7", name: "Thing One"> >> mm.save! => #<MyModel:2165734660, _id: "96579a10-f749-012c-7654-001b63ac5fc7", _rev: "1-160033dfbccd3327ffcffe94e5cd63f8", name: "Thing One"> >> mm.name = 'Changed Thing' => "Changed Thing" >> mm.save! => #<MyModel:2165734660, _id: "96579a10-f749-012c-7654-001b63ac5fc7", _rev: "2-8a95904a579942d6add4fd9e7b272165", name: "Changed Thing"> >> mm.revisions => [#<MyModel:2165559880, _id: "96579a10-f749-012c-7654-001b63ac5fc7", _rev: "2-8a95904a579942d6add4fd9e7b272165", name: "Changed Thing">, #<MyModel:2165545120, _id: "96579a10-f749-012c-7654-001b63ac5fc7", _rev: "1-160033dfbccd3327ffcffe94e5cd63f8", name: "Thing One">]
Nifty!