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 # => false
Compare 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 blank
There, 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
end
This 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 blank
Awesome! 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.