From 170956cdae043733288c2dc1440b8940af309793 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?=
 <rafaelmfranca@gmail.com>
Date: Wed, 28 Mar 2012 17:52:52 -0300
Subject: Remove code duplication in InclusionValidator and ExclusionValidator.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Orginal code by @jamescook

Closes #1352

[Rafael Mendonça França + James Cook]
---
 .../lib/active_model/validations/clusivity.rb      | 31 ++++++++++++++++++++++
 .../lib/active_model/validations/exclusion.rb      | 26 +++---------------
 .../lib/active_model/validations/inclusion.rb      | 26 +++---------------
 3 files changed, 39 insertions(+), 44 deletions(-)
 create mode 100644 activemodel/lib/active_model/validations/clusivity.rb

(limited to 'activemodel/lib')

diff --git a/activemodel/lib/active_model/validations/clusivity.rb b/activemodel/lib/active_model/validations/clusivity.rb
new file mode 100644
index 0000000000..b632a2bd6b
--- /dev/null
+++ b/activemodel/lib/active_model/validations/clusivity.rb
@@ -0,0 +1,31 @@
+require 'active_support/core_ext/range.rb'
+
+module ActiveModel
+  module Validations
+    module Clusivity
+      ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " <<
+                      "and must be supplied as the :in option of the configuration hash"
+
+      def check_validity!
+        unless [:include?, :call].any?{ |method| options[:in].respond_to?(method) }
+          raise ArgumentError, ERROR_MESSAGE
+        end
+      end
+
+    private
+
+      def include?(record, value)
+        delimiter = options[:in]
+        exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter
+        exclusions.send(inclusion_method(exclusions), value)
+      end
+
+      # In Ruby 1.9 <tt>Range#include?</tt> on non-numeric ranges checks all possible values in the
+      # range for equality, so it may be slow for large ranges. The new <tt>Range#cover?</tt>
+      # uses the previous logic of comparing a value with the range endpoints.
+      def inclusion_method(enumerable)
+        enumerable.is_a?(Range) ? :cover? : :include?
+      end
+    end
+  end
+end
diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb
index 644cc814a7..5fedb1978b 100644
--- a/activemodel/lib/active_model/validations/exclusion.rb
+++ b/activemodel/lib/active_model/validations/exclusion.rb
@@ -1,35 +1,17 @@
-require 'active_support/core_ext/range'
+require "active_model/validations/clusivity"
 
 module ActiveModel
 
   # == Active Model Exclusion Validator
   module Validations
     class ExclusionValidator < EachValidator
-      ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " <<
-                      "and must be supplied as the :in option of the configuration hash"
-
-      def check_validity!
-        unless [:include?, :call].any? { |method| options[:in].respond_to?(method) }
-          raise ArgumentError, ERROR_MESSAGE
-        end
-      end
+      include Clusivity
 
       def validate_each(record, attribute, value)
-        delimiter = options[:in]
-        exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter
-        if exclusions.send(inclusion_method(exclusions), value)
+        if include?(record, value)
           record.errors.add(attribute, :exclusion, options.except(:in).merge!(:value => value))
         end
       end
-
-    private
-
-      # In Ruby 1.9 <tt>Range#include?</tt> on non-numeric ranges checks all possible values in the
-      # range for equality, so it may be slow for large ranges. The new <tt>Range#cover?</tt>
-      # uses the previous logic of comparing a value with the range endpoints.
-      def inclusion_method(enumerable)
-        enumerable.is_a?(Range) ? :cover? : :include?
-      end
     end
 
     module HelperMethods
@@ -59,7 +41,7 @@ module ActiveModel
       # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
       #   not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
       #   method, proc or string should return or evaluate to a true or false value.
-      # * <tt>:strict</tt> - Specifies whether validation should be strict. 
+      # * <tt>:strict</tt> - Specifies whether validation should be strict.
       #   See <tt>ActiveModel::Validation#validates!</tt> for more information
       def validates_exclusion_of(*attr_names)
         validates_with ExclusionValidator, _merge_attributes(attr_names)
diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb
index 147e2ecb69..15ae7b1959 100644
--- a/activemodel/lib/active_model/validations/inclusion.rb
+++ b/activemodel/lib/active_model/validations/inclusion.rb
@@ -1,35 +1,17 @@
-require 'active_support/core_ext/range'
+require "active_model/validations/clusivity"
 
 module ActiveModel
 
   # == Active Model Inclusion Validator
   module Validations
     class InclusionValidator < EachValidator
-      ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " <<
-                      "and must be supplied as the :in option of the configuration hash"
-
-      def check_validity!
-        unless [:include?, :call].any?{ |method| options[:in].respond_to?(method) }
-          raise ArgumentError, ERROR_MESSAGE
-        end
-      end
+      include Clusivity
 
       def validate_each(record, attribute, value)
-        delimiter = options[:in]
-        exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter
-        unless exclusions.send(inclusion_method(exclusions), value)
+        unless include?(record, value)
           record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value))
         end
       end
-
-    private
-
-      # In Ruby 1.9 <tt>Range#include?</tt> on non-numeric ranges checks all possible values in the
-      # range for equality, so it may be slow for large ranges. The new <tt>Range#cover?</tt>
-      # uses the previous logic of comparing a value with the range endpoints.
-      def inclusion_method(enumerable)
-        enumerable.is_a?(Range) ? :cover? : :include?
-      end
     end
 
     module HelperMethods
@@ -59,7 +41,7 @@ module ActiveModel
       # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
       #   not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
       #   method, proc or string should return or evaluate to a true or false value.
-      # * <tt>:strict</tt> - Specifies whether validation should be strict. 
+      # * <tt>:strict</tt> - Specifies whether validation should be strict.
       #   See <tt>ActiveModel::Validation#validates!</tt> for more information
       def validates_inclusion_of(*attr_names)
         validates_with InclusionValidator, _merge_attributes(attr_names)
-- 
cgit v1.2.3