Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add ensure_exclusion_of

  • Loading branch information...
commit d8308ec74d64306baa4fb44a5216fef4b78b11fa 1 parent ead1e1d
@nashby nashby authored
View
1  lib/shoulda/matchers/active_model.rb
@@ -3,6 +3,7 @@
require 'shoulda/matchers/active_model/allow_value_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'
require 'shoulda/matchers/active_model/validate_presence_of_matcher'
require 'shoulda/matchers/active_model/validate_format_of_matcher'
require 'shoulda/matchers/active_model/validate_uniqueness_of_matcher'
View
70 lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb
@@ -0,0 +1,70 @@
+module Shoulda # :nodoc:
+ module Matchers
+ module ActiveModel # :nodoc:
+
+ # Ensure that the attribute's value is not in the range specified
+ #
+ # Options:
+ # * <tt>in_range</tt> - the range of not allowed values for this attribute
+ # * <tt>with_message</tt> - value the test expects to find in
+ # <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
+ # translation for :exclusion.
+ #
+ # Example:
+ # it { should ensure_exclusion_of(:age).in_range(30..60) }
+ #
+ def ensure_exclusion_of(attr)
+ EnsureExclusionOfMatcher.new(attr)
+ end
+
+ class EnsureExclusionOfMatcher < ValidationMatcher # :nodoc:
+
+ def in_range(range)
+ @range = range
+ @minimum = range.first
+ @maximum = range.last
+ self
+ end
+
+ def with_message(message)
+ @expected_message = message if message
+ self
+ end
+
+ def description
+ "ensure exclusion of #{@attribute} in #{@range.inspect}"
+ end
+
+ def matches?(subject)
+ super(subject)
+
+ @expected_message ||= :exclusion
+
+ allows_lower_value &&
+ disallows_minimum_value &&
+ allows_higher_value &&
+ disallows_maximum_value
+ end
+
+ private
+
+ def allows_lower_value
+ @minimum == 0 || allows_value_of(@minimum - 1, @expected_message)
+ end
+
+ def allows_higher_value
+ allows_value_of(@maximum + 1, @expected_message)
+ end
+
+ def disallows_minimum_value
+ disallows_value_of(@minimum, @expected_message)
+ end
+
+ def disallows_maximum_value
+ disallows_value_of(@maximum, @expected_message)
+ end
+ end
+
+ end
+ end
+end
View
57 spec/shoulda/active_model/ensure_exclusion_of_matcher_spec.rb
@@ -0,0 +1,57 @@
+require 'spec_helper'
+
+describe Shoulda::Matchers::ActiveModel::EnsureExclusionOfMatcher do
+
+ context "an attribute which must be excluded of a range" do
+ before do
+ @model = define_model(:example, :attr => :integer) do
+ validates_exclusion_of :attr, :in => 2..5
+ end.new
+ end
+
+ it "should accept ensuring the correct range" do
+ @model.should ensure_exclusion_of(:attr).in_range(2..5)
+ end
+
+ it "should reject ensuring excluded value" do
+ @model.should_not ensure_exclusion_of(:attr).in_range(2..6)
+ end
+
+ it "should not override the default message with a blank" do
+ @model.should ensure_exclusion_of(:attr).in_range(2..5).with_message(nil)
+ end
+ end
+
+ context "an attribute with a custom ranged value validation" do
+ before do
+ @model = define_model(:example, :attr => :string) do
+ validates_exclusion_of :attr, :in => 2..4, :message => 'not good'
+
+ end.new
+ end
+
+ it "should accept ensuring the correct range" do
+ @model.should ensure_exclusion_of(:attr).in_range(2..4).with_message(/not good/)
+ end
+ end
+
+ context "an attribute with custom range validations" do
+ before do
+ define_model :example, :attr => :integer do
+ validate :custom_validation
+ def custom_validation
+ if attr >= 2 && attr <= 5
+ errors.add(:attr, 'shoud be out of this range')
+ end
+ end
+ end
+ @model = Example.new
+ end
+
+ it "should accept ensuring the correct range and messages" do
+ @model.should ensure_exclusion_of(:attr).in_range(2..5).with_message(/shoud be out of this range/)
+ end
+
+ end
+
+end
Please sign in to comment.
Something went wrong with that request. Please try again.