To ORM Or Not To ORM Jul 23
I spend most of my time building/fixing/maintaining the infrastructure at 8tracks, but every now and then I have the opportunity to do some good old fashion ruby web application programming. This week happens to be one of those times. Everything was glorious … until I needed to make a decision.
Do I use a gem or roll my own library to handle feature X?
I hate making this decision. It’s amazing when it’s easy. For instance,
choosing to use the
aws-sdk gem over rolling my own AWS library (it sucks
just generating the stupid signature much less making an normal API call). I face
so many facets dealing with choosing a gem vs. rolling my own. I always tell
myself to suck it up and choose one so I can move on, but I never fail to
change my mind shortly afterwards. And then change it again. And again. And again.
I was in this horrible state yesterday. Working on an internal sinatra/backbone.js/mongo application I had to choose whether or not to add a mongo object relational mapping (ORM) gem or roll my own. For the past several months I didn’t need to have any ORM as simple procedural code was more than sufficient. The application logic mostly existed in the browser with Backbone.js. Sinatra was a simple pipe to load mongo data to the browser. It was extremely efficient and simple.
But I needed more logic in ruby land. I thought I could add more helper methods to manage hashes, but that soon became unmanageable (for me anyways - I have a hard enough time remembering two variables much less 10 different helper methods). The features I wanted to add begged for more behavior that suits a model class. I attempted to add one of the mongo ORMs, but some of the conventions I used in the application conflicted with the way the ORMs behaved and would require that I write code to massage the gem into place. I decided to attempt rolling my own ORM that behaved like ActiveRecord. This was fun until my Superman ego deflated and I realized the scope of what I was trying to do. As usual, the scope was huge. I was sad. I spent many hours yesterday trying out each approach but to no avail. It’s hard replicating these huge libraries!
Then something clicked last night. What I really needed was a class around the hash that would allow me to CRUD it. All other access to the hash would behave like a normal hash. This concept basically made normal ruby hashes in to super hashes. Hashes with logic. Hashes with awesome. And if you’ve ever worked with mongo, that’s basically what is stored in that database. Hashes!
I had been asking myself the wrong question the whole time. It’s not to ORM or not to ORM, but rather CRUD this hash and add a few domain specific logic to the hash. That’s not a question, I know. It punted me out of the horrible decision making though.
So, I spent my time today crafting a small library that would make it easier to manage mongo documents. It was glorious. It even has tests! And I hate writing tests.