diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 9220eae..3c2c1b7 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -852,8 +852,10 @@ module ActiveRecord
# * :unless - Specifies a method, proc or string to call to determine if the validation should
# not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The
# method, proc or string should return or evaluate to a true or false value.
+ # * :case_sensitive - Looks for an exact match. If true, enumerable object specified by :in should
+ # contain only lowercase values (default is +true+).
def validates_exclusion_of(*attr_names)
- configuration = { :on => :save }
+ configuration = { :on => :save, :case_sensitive => true }
configuration.update(attr_names.extract_options!)
enum = configuration[:in] || configuration[:within]
@@ -861,7 +863,7 @@ module ActiveRecord
raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?(:include?)
validates_each(attr_names, configuration) do |record, attr_name, value|
- if enum.include?(value)
+ if enum.include?(value) || (!configuration[:case_sensitive] && value.respond_to?(:downcase) && enum.include?(value.downcase))
record.errors.add(attr_name, :exclusion, :default => configuration[:message], :value => value)
end
end
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index c049659..1bf14bd 100644
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -708,6 +708,14 @@ class ValidationsTest < ActiveRecord::TestCase
assert_equal "option monkey is restricted", t.errors["title"]
end
+ def test_validates_exclusion_of_with_case_sensitive
+ Topic.validates_exclusion_of( :title, :in => %w( abe monkey ), :case_sensitive => false )
+
+ assert Topic.create("title" => "something", "content" => "abc").valid?
+ assert !Topic.create("title" => "monkey", "content" => "abc").valid?
+ assert !Topic.create("title" => "monKey", "content" => "abc").valid?
+ end
+
def test_validates_length_of_using_minimum
Topic.validates_length_of :title, :minimum => 5