Adam Collins' Tumblelog Follow me on Twitter, Flickr, GitHub, or StackOverflow

Aug 8

12:03 pm

Sparser Documents in CouchDB with Ruby and CouchRest

I’ve become a huge fan of CouchDB and as a Rails developer that means turning to an ORM like CouchRest to make the database access more convenient. CouchRest has a ton of helpful features and really makes it easy to slide into developing for CouchDB.

Enough with that, though. CouchRest has a particular data serialization behavior that, for me, isn’t quite Couchy enough. Empty strings and null attributes still get stored in the database even though they contain “nothing.” To me, that’s not very useful and just leaves empty attributes in the database. These empty attributes can also interfere with the CouchDB views (indexes) if not handled correctly. In my view, one of the main benefits of a document-based schema-less database is not having to store null attributes and empty strings.

Other developers may disagree with this, though, and so rather than file this as bug or fork the CouchRest project on GitHub, I just made a little patch for the CouchRest::ExtendedDocument (or the derived CouchRestRails::Document) database model class that prevents empty attributes from getting stored with the documents:

class Thing < CouchRestRails::Document
  use_database 'webapp'

  before_save :sparse_attributes!

  property :owner
  property :name
  property :date, :cast_as => 'Date', :init_method => :parse
  property :content
  property :notes

  timestamps!

  validates_presence_of :owner
  validates_presence_of :name

  view_by :owner, :name

private

  def sparse_attributes!
    properties.each do |property|
      name = property.name.to_s
      value = send(name)
      delete(name) if value.nil? or value == ''
    end
  end

end

The sparse_attributes! method simply goes through each one of the model’s attributes (properties) and deletes the empty ones. The before_save line just ensures that sparse_attributes! is called just before the document data is sent to CouchDB for document creation or updates. One caveat I’ve found is that empty attributes will not be removed if the model class doesn’t know about the attribute name, but that’s a small consideration in my particular case.