From 9e77132b34d17545dc99047898f1ce5f2640036e Mon Sep 17 00:00:00 2001 From: Tiago Cardoso Date: Tue, 19 Feb 2013 11:09:13 +0100 Subject: [PATCH] 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) --- lib/shoulda/matchers/active_model.rb | 1 + .../active_model/comparison_matcher.rb | 52 +++++++++++++++++++ .../validate_numericality_of_matcher.rb | 30 +++++++++-- .../active_model/comparison_matcher_spec.rb | 40 ++++++++++++++ 4 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 lib/shoulda/matchers/active_model/comparison_matcher.rb create mode 100644 spec/shoulda/matchers/active_model/comparison_matcher_spec.rb diff --git a/lib/shoulda/matchers/active_model.rb b/lib/shoulda/matchers/active_model.rb index 2d950bf0..f3ccdf02 100644 --- a/lib/shoulda/matchers/active_model.rb +++ b/lib/shoulda/matchers/active_model.rb @@ -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' diff --git a/lib/shoulda/matchers/active_model/comparison_matcher.rb b/lib/shoulda/matchers/active_model/comparison_matcher.rb new file mode 100644 index 00000000..6aadb9e9 --- /dev/null +++ b/lib/shoulda/matchers/active_model/comparison_matcher.rb @@ -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 diff --git a/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb index 4c1ec318..ec034e86 100644 --- a/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb @@ -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 diff --git a/spec/shoulda/matchers/active_model/comparison_matcher_spec.rb b/spec/shoulda/matchers/active_model/comparison_matcher_spec.rb new file mode 100644 index 00000000..211f209d --- /dev/null +++ b/spec/shoulda/matchers/active_model/comparison_matcher_spec.rb @@ -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