At my work (Give.it) we had a REST API that used Ruby’s DataMapper ORM for database operations. Initially this seemed to work okay but as the API became more complex we stumbled into a growing number of pitfalls. While a lot of the basic functionality was covered by the existing code I found that it was deficient in key areas such as:
- poor error handling and detection – a validation issue on a child object could prevent a parent object from saving but there was no way to find this out using DMs error functions
- the built in JSON functions were buggy and needed to be replaced
- DM generated ridiculous numbers of queries
- I had to write my own functions to filter results as the built in ones were faulty
- DM was missing basic features such as DataMapper::PropertySet.size to get the number of results in a set
Other issues I came across:
- DM cannot lock tables or do proper transactions when writing making it possible for two processes to overwrite data at the same time
- There are several well-known serious issues with DM’s 1:1 relationship model
- Basic functionality such as paging has to be solved by installing 3rd party packages
- Mostly relationships are set up “magically” meaning you have little control over how they are done
- Auto-migrations (when you change DB structure) frequently cause major issues – e.g. if you rename a field it creates two fields!
- Destroying records is frequently impossible, you have to work around this by adding a status and setting that to “deleted”
- Most of the DM core has not been updated in years – as much as two or three years for some components.
- DM 1.3.0 was already a year behind schedule at the time we dropped it
- dm-pager can tell you how many pages of records there are, but not how many records in total
- DM’s query syntax makes doing “OR” queries extremely difficult
With all of the above problems it should come as no surprise that DM’s GitHub projects were full of unresolved issues. In fact even the dm-core project, the main core of the ORM, had over 100 unresolved bugs. Not a good sign at all.
It was clear that continuing to use DataMapper was an unviable option so I started looking at alternatives. ActiveRecord was, of course, one of the first things I looked at. Being widely used (especially as part of Rails) it was high on the list, however after considerable research I decided to go with Sequel which has a rock solid reputation and zero (yes, zero) outstanding bugs. Jeremy Evans does an excellent job of keeping Sequel bug free 🙂
In the end we decided that our best option was to rewrite our API from scratch using Sequel. Total rewrite time was about 6 weeks, of that I would estimate that 2 weeks was spent learning Sequel and writing the code that uses it. The end result is an API that performs 10-20 times faster. I attribute about 50% of that to Sequel and the other 50% to smarter Ruby code.
If you are using DataMapper in your project and are experiencing problems then I highly recommend that you ditch it and go with a better ORM such as ActiveRecord or Sequel.