Add comparison submatchers to validate_numericality_of

You can now use the following with validate_numericality_of:

* is_greater_than (corresponds to :greater_than)
* is_greater_than_or_equal_to (corresponds to :greater_than_or_equal_to)
* is_equal_to (corresponds to :equal_to)
* is_less_than (corresponds_to :less_than)
* is_less_than_or_equal_to (corresponds_to :less_than_or_equal_to)
This commit is contained in:
Tiago Cardoso 2013-02-19 11:09:13 +01:00 committed by Elliot Winkler
parent 2065a654e6
commit 9e77132b34
4 changed files with 120 additions and 3 deletions

View File

@ -6,6 +6,7 @@ require 'shoulda/matchers/active_model/allow_value_matcher'
require 'shoulda/matchers/active_model/disallow_value_matcher'
require 'shoulda/matchers/active_model/only_integer_matcher'
require 'shoulda/matchers/active_model/odd_even_number_matcher'
require 'shoulda/matchers/active_model/comparison_matcher'
require 'shoulda/matchers/active_model/ensure_length_of_matcher'
require 'shoulda/matchers/active_model/ensure_inclusion_of_matcher'
require 'shoulda/matchers/active_model/ensure_exclusion_of_matcher'

View File

@ -0,0 +1,52 @@
module Shoulda # :nodoc:
module Matchers
module ActiveModel # :nodoc:
# Examples:
# it { should validate_numericality_of(:attr).
# is_greater_than(6).
# less_than(20)...(and so on) }
class ComparisonMatcher < ValidationMatcher
def initialize(value, operator)
@value = value
@operator = operator
end
def for(attribute)
@attribute = attribute
self
end
def matches?(subject)
@subject = subject
disallows_value_of(value_to_compare)
end
def allowed_types
'integer'
end
private
def value_to_compare
case @operator
when :> then [@value, @value - 1].sample
when :>= then @value - 1
when :== then @value
when :< then [@value, @value + 1].sample
when :<= then @value + 1
end
end
def expectation
case @operator
when :> then "greater than"
when :>= then "greater than or equal to"
when :== then "equal to"
when :< then "less than"
when :<= then "less than or equal to"
end
end
end
end
end
end

View File

@ -32,8 +32,32 @@ module Shoulda # :nodoc:
end
def only_integer
only_integer_matcher = OnlyIntegerMatcher.new(@attribute)
add_submatcher(only_integer_matcher)
add_submatcher(OnlyIntegerMatcher.new(@attribute))
self
end
def is_greater_than(value)
add_submatcher(ComparisonMatcher.new(value, :>).for(@attribute))
self
end
def is_greater_than_or_equal_to(value)
add_submatcher(ComparisonMatcher.new(value, :>=).for(@attribute))
self
end
def is_equal_to(value)
add_submatcher(ComparisonMatcher.new(value, :==).for(@attribute))
self
end
def is_less_than(value)
add_submatcher(ComparisonMatcher.new(value, :<).for(@attribute))
self
end
def is_less_than_or_equal_to(value)
add_submatcher(ComparisonMatcher.new(value, :<=).for(@attribute))
self
end
@ -98,7 +122,7 @@ module Shoulda # :nodoc:
end
def failing_submatchers
@failing_submatchers ||= @submatchers.select { |matcher| !matcher.matches?(@subject) }
@failing_submatchers ||= @submatchers.select { |matcher| !matcher.matches?(@subject.dup) }
end
def allowed_types

View File

@ -0,0 +1,40 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ComparisonMatcher do
context 'is_greater_than' do
it { instance_with_validations(:greater_than => 2).should matcher.is_greater_than(2) }
it { instance_without_validations.should_not matcher.is_greater_than(2) }
end
context 'greater_than_or_equal_to' do
it { instance_with_validations(:greater_than_or_equal_to => 2).should matcher.is_greater_than_or_equal_to(2) }
it { instance_without_validations.should_not matcher.is_greater_than_or_equal_to(2) }
end
context 'less_than' do
it { instance_with_validations(:less_than => 2).should matcher.is_less_than(2) }
it { instance_without_validations.should_not matcher.is_less_than(2) }
end
context 'less_than_or_equal_to' do
it { instance_with_validations(:less_than_or_equal_to => 2).should matcher.is_less_than_or_equal_to(2) }
it { instance_without_validations.should_not matcher.is_less_than_or_equal_to(2) }
end
def instance_with_validations(options = {})
define_model :example, :attr => :string do
validates_numericality_of :attr, options
attr_accessible :attr
end.new
end
def instance_without_validations
define_model :example, :attr => :string do
attr_accessible :attr
end.new
end
def matcher
validate_numericality_of(:attr)
end
end