So today I was messing around with DataMapper and something weird happened. I was porting some of the model code over from the Restful_auth plugin by Rick Olson to DataMapper when I hit a bug, or so I thought.
I’d was trying to change the user’s password and then calling the save method, but each time I did so it would return false. Now the first thing I did was to check the errors attribute on the model, which strangely was empty. At first I scratched my head for a minute puzzled at what was going on when suddenly it occurred to me the foolishness of what I was doing.
The thing is that DataMapper is smarter than ActiveRecord.. Alot smarter. One of the clever things it does is only update rows in the database that have changed unlike AR which saves the entire record to the DB even if only one field has changed. Not very performant. Another thing DataMapper does which is related to this is that it will persist the model to the database if any attribute changes that it manages when you explicitly call save otherwise it won’t do anything and just return false. Aha! There’s a hint. Now the model code from the Restful_auth plugin uses a ‘virtual’ attribute called password which is basically the password in a state of plaintext before it’s encrypted, assigned to the crypted_password attribute and saved. Because the password attribute on the model is not persisted to the database and therefore not strictly managed by DataMapper the model was never marked as dirty when I changed the password attribute. In fact because the model wasn’t marked as dirty the before_save callback also wasn’t being called either so the crypted_password attribute which was managed by DataMapper was not altered either. As explained before, this wouldn’t have been a problem if I’d used AR as it’s pretty dumb when it saves.
So the lesson of this tale is that you should treat DataMapper with more respect, beware of all it’s subtleties and not treat it like it’s impaired cousin ActiveRecord.
