Skip to content
This repository has been archived by the owner on Apr 17, 2018. It is now read-only.

Commit

Permalink
[dm-validations] Make it possible to use callable objects for message…
Browse files Browse the repository at this point in the history
…s, requires Edge Extlib

This makes it possible to construct complex custom error messages and not add
more and more and more ad hoc error messages to default set

 * ValidationErrors objects are now aware of models they are attached to (#model accessor)
 * For pure Ruby objects, if :message is a callable, model (object) is yielded to it
 * For DM resources, if :message is a callable, model AND property are yielded to it

[#769 state:resolved]
  • Loading branch information
michaelklishin committed Mar 26, 2009
1 parent 1cebda6 commit fb4f889
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 12 deletions.
2 changes: 1 addition & 1 deletion dm-validations/lib/dm-validations.rb
Expand Up @@ -73,7 +73,7 @@ def save!
# Return the ValidationErrors
#
def errors
@errors ||= ValidationErrors.new
@errors ||= ValidationErrors.new(self)
end

# Mark this resource as validatable. When we validate associations of a
Expand Down
22 changes: 20 additions & 2 deletions dm-validations/lib/dm-validations/validation_errors.rb
Expand Up @@ -41,6 +41,13 @@ def self.default_error_message(key, field, *values)
@@default_error_messages[key] % [field, *values].flatten
end

attr_reader :model

def initialize(model)
@model = model
@errors = {}
end

# Clear existing validation errors.
def clear!
errors.clear
Expand All @@ -52,6 +59,17 @@ def clear!
# @param [Symbol] field_name the name of the field that caused the error
# @param [String] message the message to add
def add(field_name, message)
# see 6abe8fff in extlib, but don't enforce
# it unless Edge version is installed
if message.respond_to?(:try_call)
# DM model
message = if model.class.respond_to?(:properties)
message.try_call(model, model.class.properties[field_name])
else
# pure Ruby object
message.try_call(model)
end
end
(errors[field_name] ||= []) << message
end

Expand Down Expand Up @@ -80,7 +98,7 @@ def each
end

def empty?
entries.empty?
@errors.empty?
end

def method_missing(meth, *args, &block)
Expand All @@ -89,7 +107,7 @@ def method_missing(meth, *args, &block)

private
def errors
@errors ||= {}
@errors
end

end # class ValidationErrors
Expand Down
Expand Up @@ -12,7 +12,8 @@

describe "reservation with mismatched seats number", :shared => true do
it "has meaningful error message" do
@model.errors.on(:number_of_seats).should include("Number of seats does not match the confirmation")
# Proc gets expanded here
@model.errors.on(:number_of_seats).should include("Reservation requires confirmation for number_of_seats")
end
end

Expand Down
Expand Up @@ -29,7 +29,9 @@ class Reservation
#

validates_is_confirmed :person_name, :allow_nil => false
validates_is_confirmed :number_of_seats, :confirm => :seats_confirmation
validates_is_confirmed :number_of_seats, :confirm => :seats_confirmation, :message => Proc.new { |model, property|
"%s requires confirmation for %s" % [model.class.name.split("::").last, property.name]
}
end # Reservation
end # Fixtures
end # Validate
Expand Down
Expand Up @@ -15,7 +15,9 @@ class Country
#

validates_present :name, :when => [:default, :adding_to_encyclopedia]
validates_present :population, :when => :adding_to_encyclopedia
validates_present :population, :when => :adding_to_encyclopedia, :message => Proc.new { |record|
"population really needs to be specified when adding %s to encyclopedia" % [record.class.name]
}

validates_length :name, :in => (4..50)

Expand Down Expand Up @@ -64,6 +66,12 @@ def initialize(name, population = nil)
@model.should_not be_valid(:adding_to_encyclopedia)
@model.should_not be_valid_for_adding_to_encyclopedia
end

it "has a meaningful error message" do
# trigger validation => have errors on the object
@model.valid_for_adding_to_encyclopedia?
@model.errors.on(:population).should == ["population really needs to be specified when adding PureRubyObjects::Country to encyclopedia"]
end
end


Expand Down Expand Up @@ -96,16 +104,16 @@ def initialize(name, population = nil)
@model.name = "It"
@model.valid?
end

it_should_behave_like "object invalid in default context"

it "has errors on name" do
@model.errors.on(:name).should_not be_blank
end

it "is valid in encyclopedia context" do
@model.should be_valid(:adding_to_encyclopedia)
@model.should be_valid_for_adding_to_encyclopedia
end
end
end
end
2 changes: 1 addition & 1 deletion dm-validations/spec/unit/validation_errors/adding_spec.rb
Expand Up @@ -4,7 +4,7 @@

describe DataMapper::Validate::ValidationErrors do
before :all do
@model = DataMapper::Validate::ValidationErrors.new
@model = DataMapper::Validate::ValidationErrors.new(Object.new)
end

describe "after first error being added" do
Expand Down
Expand Up @@ -4,7 +4,7 @@

describe DataMapper::Validate::ValidationErrors do
before :all do
@model = DataMapper::Validate::ValidationErrors.new
@model = DataMapper::Validate::ValidationErrors.new(Object.new)
end

describe "initially" do
Expand Down
Expand Up @@ -4,7 +4,7 @@

describe DataMapper::Validate::ValidationErrors do
before :all do
@model = DataMapper::Validate::ValidationErrors.new
@model = DataMapper::Validate::ValidationErrors.new(Object.new)
@model.add(:ip_address, "must have valid format")
@model.add(:full_name, "can't be blank")
end
Expand Down

0 comments on commit fb4f889

Please sign in to comment.