diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 049b093618..108586b8df 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -8,9 +8,26 @@ module ActiveModel ":in option of the configuration hash" unless options[:in].respond_to?(:include?) end - def validate_each(record, attribute, value) - unless options[:in].include?(value) - record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + # On Ruby 1.9 Range#include? checks all possible values in the range for equality, + # so it may be slow for large ranges. The new Range#cover? uses the previous logic + # of comparing a value with the range endpoints. + if (1..2).respond_to?(:cover?) + def validate_each(record, attribute, value) + included = if options[:in].is_a?(Range) + options[:in].cover?(value) + else + options[:in].include?(value) + end + + unless included + record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + end + end + else + def validate_each(record, attribute, value) + unless options[:in].include?(value) + record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + end end end end diff --git a/activemodel/test/cases/validations/inclusion_validation_test.rb b/activemodel/test/cases/validations/inclusion_validation_test.rb index 0716b4f087..62f2ec785d 100644 --- a/activemodel/test/cases/validations/inclusion_validation_test.rb +++ b/activemodel/test/cases/validations/inclusion_validation_test.rb @@ -10,6 +10,15 @@ class InclusionValidationTest < ActiveModel::TestCase Topic.reset_callbacks(:validate) end + def test_validates_inclusion_of_range + Topic.validates_inclusion_of( :title, :in => 'aaa'..'bbb' ) + assert Topic.new("title" => "bbc", "content" => "abc").invalid? + assert Topic.new("title" => "aa", "content" => "abc").invalid? + assert Topic.new("title" => "aaa", "content" => "abc").valid? + assert Topic.new("title" => "abc", "content" => "abc").valid? + assert Topic.new("title" => "bbb", "content" => "abc").valid? + end + def test_validates_inclusion_of Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) )