Model.errors: DataMapper and ActiveRecord Validations
While continuing to work on my form validations I dug down into DataMapper to see what my options for error handling were, and also to see how I could mirror its behavior in my in-memory models if I wanted to.
DataMapper handles the errors on model validation very similar to ActiveRecord, in that anything that doesn’t pass validation gets stuck into a hash that is stored in the @errors
attribute on the model. For example, if a title is required for a Blogpost object but you submit a form without one, your @blogpost.errors is now something like {:title => “Title must be required”}.
Anyone who has ever seen a scaffolded Rails form has seen this @errors hash in use. At the top of each “_form” partial is:
<% if @item.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@item.errors.count, "error") %> prohibited this item from being saved:</h2>
<ul>
<% @item.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Although I’m not using errors entirely the same way as Rails, for now I decided that for basic “validating presence of” an attribute I would go ahead and keep it on my in-memory models. It doesn’t seem like too much of a stretch to say that it is the object’s responsibility to make sure that its required attributes are present and accounted for. Then I know if an object is valid by whether or not it has any errors. If there are any, then I can use those errors when I re-render a form to tell a user exactly what the problem is (kind of like the code above, except that I explicitly send the errors hash to the view).
However, as I built this out for my in-memory models, I can already start to see how some of those validation, initialize and update methods are borderline SRP violations. Once I start to add any other sort of validations besides presence then I’ll probably want to delegate it to some sort of Validation class.