When Ruby on Rails first hit the scene, what attracted many of us to it was ActiveRecord. By providing a declarative syntax for describing relationships, validations, and callbacks it provided an elegance to model code that makes programming a lot more fun. Over the past couple of years ActiveRecord has received a lot of love, with has_many :through and improved caching options being the key additions I’ve enjoyed. But despite all that it’s given, ActiveRecord is clearly not the last word in Object Relational Mappers and it’s been good to see increased attention for some alternative Ruby ORMs such as DataMapper.
DataMapper shares a lot of syntax with ActiveRecord but promises a few new features, such as a more succinct find syntax, eg.
# Find first entry in my_objects table MyObject.find(:first) # ActiveRecord MyObject.first # DataMapper # Find all entries in my_objects table MyObject.find(:all) # ActiveRecord MyObject.all # DataMapper
and perhaps more usefully, improved finder options. Edited from the DataMapper site:
# 'gt' means greater-than. We also do 'lt'. Person.all(:age.gt => 30) # 'gte' means greather-than-or-equal-to. We also do 'lte'. Person.all(:age.gte => 30) Person.all(:name.not => 'bob') # If the value of a pair is an Array, we do an IN-clause for you. Person.all(:name.like => 'S%', :id => [1, 2, 3, 4, 5]) # Does a NOT IN () clause for you. Person.all(:name.not => ['bob','rick','steve'])
You can approximate that functionality with some Rails plugins, and of course you can use the :conditions parameter to an ActiveRecord finder to do the same queries, but there’s something nice about being able to do it all in Ruby. (You can also fall back to ActiveRecord like syntax)
Most uses of DataMapper I’ve seen so far have been standalone, or in conjunction with merb, but I decided to give it a try by converting an existing rails app. Given how much similarity there is in syntax it seemed like it would be fairly easy to convert a few models and see how it compared. Unfortunately, it’s not that easy.
It’s pretty rare to build a rails app without plugins, and most plugins that affect models do so by extending ActiveRecord::Base. Since by using DataMapper you’re breaking away from ActiveRecord::Base, those plugins won’t work without invasive surgery. Similarly, DataMapper doesn’t support AR’s validation syntax and while it will soon have validations of its own, it looks unlikely that they’ll be compatible. It might well be possible to write a plugin that makes many other plugins work by examining ActiveRecord::Base.extended_by, and that could provide a translation layer to allow ActiveRecord validations to work with DataMapper, but that begins to be a lot of work for very little return.
Where DataMapper may really help Rails developers is in introducing more competition into the Ruby ORM world. By taking some radically different design decisions, particularly with regards to migrations and column specifications DataMapper allows us to see a different, but similarly elegant way of doing things, and hopefully ideas will percolate back into ActiveRecord just as AR has clearly inspired DataMapper. Personally I am looking forward to using DataMapper in my next non-rails ruby project, but found the exploration a useful reminder of how much of rails’ success is in its coherency as a stack.