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.