Improve error message handling in ValidateNumericalityOfMatcher and OnlyIntegerMatcher.

This commit is contained in:
Reade Harris 2012-10-23 12:30:18 -04:00 committed by Jason Draper
parent 6ba8c9f1a1
commit 8a563c18a5
6 changed files with 71 additions and 20 deletions

View File

@ -3,7 +3,7 @@ module Shoulda # :nodoc:
module ActiveModel # :nodoc:
class DisallowValueMatcher # :nodoc:
def initialize(value)
@allow_matcher = Shoulda::Matchers::ActiveModel::AllowValueMatcher.new(value)
@allow_matcher = AllowValueMatcher.new(value)
end
def matches?(subject)

View File

@ -2,22 +2,31 @@ module Shoulda # :nodoc:
module Matchers
module ActiveModel # :nodoc:
class OnlyIntegerMatcher # :nodoc:
NON_INTEGER_VALUE = 0.1
def initialize(attribute)
@attribute = attribute
@disallow_value_matcher = DisallowValueMatcher.new(NON_INTEGER_VALUE).
for(attribute).
with_message(:not_an_integer)
end
def matches?(subject)
matcher = AllowValueMatcher.new(0.1).for(@attribute)
!matcher.matches?(subject)
@disallow_value_matcher.matches?(subject)
end
def with_message(message)
@disallow_value_matcher.with_message(message)
self
end
def allowed_types
"integer"
end
def failure_message
@disallow_value_matcher.failure_message
end
end
end
end

View File

@ -18,6 +18,8 @@ module Shoulda # :nodoc:
end
class ValidateNumericalityOfMatcher
NON_NUMERIC_VALUE = 'abcd'
def initialize(attribute)
@attribute = attribute
@options = {}
@ -29,18 +31,16 @@ module Shoulda # :nodoc:
def only_integer
only_integer_matcher = OnlyIntegerMatcher.new(@attribute)
add_submatcher(only_integer_matcher)
self
end
def with_message(message)
@expected_message = message
@submatchers.each { |matcher| matcher.with_message(message) }
self
end
def matches?(subject)
@subject = subject
set_expected_message_on_submatchers
submatchers_match?
end
@ -49,27 +49,33 @@ module Shoulda # :nodoc:
end
def failure_message
@disallow_value_matcher.failure_message
submatcher_failure_messages.last
end
private
def add_disallow_value_matcher
@disallow_value_matcher = DisallowValueMatcher.new('abcd').for(@attribute)
add_submatcher(@disallow_value_matcher)
disallow_value_matcher = DisallowValueMatcher.new(NON_NUMERIC_VALUE).
for(@attribute).
with_message(:not_a_number)
add_submatcher(disallow_value_matcher)
end
def add_submatcher(submatcher)
@submatchers << submatcher
end
def set_expected_message_on_submatchers
message = @expected_message || :not_a_number
@submatchers.each { |matcher| matcher.with_message(message) }
def submatchers_match?
failing_submatchers.empty?
end
def submatchers_match?
@submatchers.all? { |matcher| matcher.matches?(@subject) }
def submatcher_failure_messages
failing_submatchers.map(&:failure_message)
end
def failing_submatchers
@failing_submatchers ||= @submatchers.select { |matcher| !matcher.matches?(@subject) }
end
def allowed_types
@ -78,7 +84,7 @@ module Shoulda # :nodoc:
end
def submatcher_allowed_types
@submatchers.map(&:allowed_types).reject { |type| type.empty? }
@submatchers.map(&:allowed_types).reject(&:empty?)
end
end
end

View File

@ -42,7 +42,7 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher do
end
it "delegates its failure message to its allow matcher's negative failure message" do
allow_matcher = stub_everything(negative_failure_message: "allow matcher failure")
allow_matcher = stub_everything(:negative_failure_message => "allow matcher failure")
Shoulda::Matchers::ActiveModel::AllowValueMatcher.stubs(:new).returns(allow_matcher)
matcher = new_matcher("abcde")

View File

@ -25,6 +25,27 @@ describe Shoulda::Matchers::ActiveModel::OnlyIntegerMatcher do
end
end
context "given an attribute that only allows integer values with a custom validation message" do
before do
define_model :example, :attr => :string do
validates_numericality_of :attr, { :only_integer => true, :message => 'custom' }
end
@model = Example.new
end
it "should only allow integer values for that attribute with that message" do
matcher = new_matcher(:attr)
matcher.with_message(/custom/)
matcher.matches?(@model).should be_true
end
it "should not allow integer values for that attribute with another message" do
matcher = new_matcher(:attr)
matcher.with_message(/wrong/)
matcher.matches?(@model).should be_false
end
end
context "given an attribute that allows values other than integers" do
before do
@model = define_model(:example, :attr => :string).new
@ -34,6 +55,12 @@ describe Shoulda::Matchers::ActiveModel::OnlyIntegerMatcher do
matcher = new_matcher(:attr)
matcher.matches?(@model).should be_false
end
it "should fail with the ActiveRecord :not_an_integer message" do
matcher = new_matcher(:attr)
matcher.matches?(@model)
matcher.failure_message.should include 'Expected errors to include "must be an integer"'
end
end
def new_matcher(attribute)

View File

@ -25,10 +25,19 @@ describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher do
matcher.matches?(@model).should be_true
end
it "should not enforce integer values for that attribute" do
matcher = new_matcher(:attr)
matcher.only_integer
matcher.matches?(@model).should be_false
context "when asked to enforce integer values for that attribute" do
it "should not match" do
matcher = new_matcher(:attr)
matcher.only_integer
matcher.matches?(@model).should be_false
end
it "should fail with the ActiveRecord :not_an_integer message" do
matcher = new_matcher(:attr)
matcher.only_integer
matcher.matches?(@model)
matcher.failure_message.should include 'Expected errors to include "must be an integer"'
end
end
end