Improve error message handling in ValidateNumericalityOfMatcher and OnlyIntegerMatcher.
This commit is contained in:
parent
6ba8c9f1a1
commit
8a563c18a5
|
@ -3,7 +3,7 @@ module Shoulda # :nodoc:
|
||||||
module ActiveModel # :nodoc:
|
module ActiveModel # :nodoc:
|
||||||
class DisallowValueMatcher # :nodoc:
|
class DisallowValueMatcher # :nodoc:
|
||||||
def initialize(value)
|
def initialize(value)
|
||||||
@allow_matcher = Shoulda::Matchers::ActiveModel::AllowValueMatcher.new(value)
|
@allow_matcher = AllowValueMatcher.new(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches?(subject)
|
def matches?(subject)
|
||||||
|
|
|
@ -2,22 +2,31 @@ module Shoulda # :nodoc:
|
||||||
module Matchers
|
module Matchers
|
||||||
module ActiveModel # :nodoc:
|
module ActiveModel # :nodoc:
|
||||||
class OnlyIntegerMatcher # :nodoc:
|
class OnlyIntegerMatcher # :nodoc:
|
||||||
|
NON_INTEGER_VALUE = 0.1
|
||||||
|
|
||||||
def initialize(attribute)
|
def initialize(attribute)
|
||||||
@attribute = attribute
|
@attribute = attribute
|
||||||
|
@disallow_value_matcher = DisallowValueMatcher.new(NON_INTEGER_VALUE).
|
||||||
|
for(attribute).
|
||||||
|
with_message(:not_an_integer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches?(subject)
|
def matches?(subject)
|
||||||
matcher = AllowValueMatcher.new(0.1).for(@attribute)
|
@disallow_value_matcher.matches?(subject)
|
||||||
!matcher.matches?(subject)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_message(message)
|
def with_message(message)
|
||||||
|
@disallow_value_matcher.with_message(message)
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_types
|
def allowed_types
|
||||||
"integer"
|
"integer"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def failure_message
|
||||||
|
@disallow_value_matcher.failure_message
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,8 @@ module Shoulda # :nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
class ValidateNumericalityOfMatcher
|
class ValidateNumericalityOfMatcher
|
||||||
|
NON_NUMERIC_VALUE = 'abcd'
|
||||||
|
|
||||||
def initialize(attribute)
|
def initialize(attribute)
|
||||||
@attribute = attribute
|
@attribute = attribute
|
||||||
@options = {}
|
@options = {}
|
||||||
|
@ -29,18 +31,16 @@ module Shoulda # :nodoc:
|
||||||
def only_integer
|
def only_integer
|
||||||
only_integer_matcher = OnlyIntegerMatcher.new(@attribute)
|
only_integer_matcher = OnlyIntegerMatcher.new(@attribute)
|
||||||
add_submatcher(only_integer_matcher)
|
add_submatcher(only_integer_matcher)
|
||||||
|
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_message(message)
|
def with_message(message)
|
||||||
@expected_message = message
|
@submatchers.each { |matcher| matcher.with_message(message) }
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches?(subject)
|
def matches?(subject)
|
||||||
@subject = subject
|
@subject = subject
|
||||||
set_expected_message_on_submatchers
|
|
||||||
submatchers_match?
|
submatchers_match?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -49,27 +49,33 @@ module Shoulda # :nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
def failure_message
|
def failure_message
|
||||||
@disallow_value_matcher.failure_message
|
submatcher_failure_messages.last
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def add_disallow_value_matcher
|
def add_disallow_value_matcher
|
||||||
@disallow_value_matcher = DisallowValueMatcher.new('abcd').for(@attribute)
|
disallow_value_matcher = DisallowValueMatcher.new(NON_NUMERIC_VALUE).
|
||||||
add_submatcher(@disallow_value_matcher)
|
for(@attribute).
|
||||||
|
with_message(:not_a_number)
|
||||||
|
|
||||||
|
add_submatcher(disallow_value_matcher)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_submatcher(submatcher)
|
def add_submatcher(submatcher)
|
||||||
@submatchers << submatcher
|
@submatchers << submatcher
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_expected_message_on_submatchers
|
def submatchers_match?
|
||||||
message = @expected_message || :not_a_number
|
failing_submatchers.empty?
|
||||||
@submatchers.each { |matcher| matcher.with_message(message) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def submatchers_match?
|
def submatcher_failure_messages
|
||||||
@submatchers.all? { |matcher| matcher.matches?(@subject) }
|
failing_submatchers.map(&:failure_message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def failing_submatchers
|
||||||
|
@failing_submatchers ||= @submatchers.select { |matcher| !matcher.matches?(@subject) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_types
|
def allowed_types
|
||||||
|
@ -78,7 +84,7 @@ module Shoulda # :nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
def submatcher_allowed_types
|
def submatcher_allowed_types
|
||||||
@submatchers.map(&:allowed_types).reject { |type| type.empty? }
|
@submatchers.map(&:allowed_types).reject(&:empty?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,7 +42,7 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "delegates its failure message to its allow matcher's negative failure message" do
|
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)
|
Shoulda::Matchers::ActiveModel::AllowValueMatcher.stubs(:new).returns(allow_matcher)
|
||||||
|
|
||||||
matcher = new_matcher("abcde")
|
matcher = new_matcher("abcde")
|
||||||
|
|
|
@ -25,6 +25,27 @@ describe Shoulda::Matchers::ActiveModel::OnlyIntegerMatcher do
|
||||||
end
|
end
|
||||||
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
|
context "given an attribute that allows values other than integers" do
|
||||||
before do
|
before do
|
||||||
@model = define_model(:example, :attr => :string).new
|
@model = define_model(:example, :attr => :string).new
|
||||||
|
@ -34,6 +55,12 @@ describe Shoulda::Matchers::ActiveModel::OnlyIntegerMatcher do
|
||||||
matcher = new_matcher(:attr)
|
matcher = new_matcher(:attr)
|
||||||
matcher.matches?(@model).should be_false
|
matcher.matches?(@model).should be_false
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def new_matcher(attribute)
|
def new_matcher(attribute)
|
||||||
|
|
|
@ -25,11 +25,20 @@ describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher do
|
||||||
matcher.matches?(@model).should be_true
|
matcher.matches?(@model).should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not enforce integer values for that attribute" do
|
context "when asked to enforce integer values for that attribute" do
|
||||||
|
it "should not match" do
|
||||||
matcher = new_matcher(:attr)
|
matcher = new_matcher(:attr)
|
||||||
matcher.only_integer
|
matcher.only_integer
|
||||||
matcher.matches?(@model).should be_false
|
matcher.matches?(@model).should be_false
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
context "given a numeric attribute which must be integer" do
|
context "given a numeric attribute which must be integer" do
|
||||||
|
|
Loading…
Reference in New Issue