DataMapper: Noisy Failures
Some have argued that there is fundamental flaw in DataMapper: that it "considers booleans to be a superior solution to exceptions." That is, the library does not actively tell you what went wrong when you try to save a record and it fails.
Simple Example
Consider this simple example:
class Person
include DataMapper::Resource
property :id, Serial
property :name, String, :required => true
end
p = Person.new
p.save # => falseCompare this to the behavior you get after requiring dm-noisy-failures:
require "dm_noisy_failures" # or dm-noisy-failures
p = Person.new
p.save # => DataMapper::SaveFailureError: Person: Name must not be blankThere, isn't that better?
Slightly More Complex Example
The DataMapper documentation suggests a way to do something similar to the above:
def save_record(record)
if record.save
# The record saved successfully.
else
puts "Errors:"
record.errors.each do |e|
puts e
end
end
endThis works just fine for the simple example above. But what if we change things up a bit?
class Person
has n, :accounts
end
class Account
include DataMapper::Resource
belongs_to :person
property :id, Serial
property :person_id, Integer
property :name, String, :required => true
end
p = Person.new(:name => "John")
p.accounts << Account.new
save_record(p) # => Errors:What happened? Why don't we see any errors? Because the record passed to save_record doesn't have any; it's the child record that has the errors.
Now, let's try that again with dm-noisy-failures required:
require "dm_noisy_failures"
p = Person.new(:name => "John")
p.accounts << Account.new
save_record(p) # => DataMapper::SaveFailureError: Account: Name must not be blankAwesome! Right?
Methods Affected
This gem aliases the default DataMapper methods save, update, create, and destroy with ? equivalents (save?, etc.) which return true or false. The one exception is create?, which returns either a resource object or nil.
All four methods are then replaced with variations that throw exceptions with informative error messages.
This means that for each operation, there are three options to choose from:
-
save?(the old default): return true or false -
save(the new default): throw exceptions on failure -
save!(already part of DataMapper): save without validating
Requirements
This library's only dependency is DataMapper itself. Note that you should require dm-noisy-failures before defining any of your models.