From deca62c0389e1c01bd3e94d370eaeee354e75a59 Mon Sep 17 00:00:00 2001 From: Hugo Peixoto Date: Sun, 9 Aug 2009 00:31:19 +0100 Subject: [PATCH] Added a :case_sensitive => :db option to validates_uniqueness_of, which uses the database's case-sensitivity mode for comparisons. Ported the patch submitted by Phil Ross --- activerecord/lib/active_record/validations.rb | 11 +++++++++-- activerecord/test/cases/validations_test.rb | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index d2d12b8..17eb597 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -628,7 +628,9 @@ module ActiveRecord # Configuration options: # * :message - Specifies a custom error message (default is: "has already been taken"). # * :scope - One or more columns by which to limit the scope of the uniqueness constraint. - # * :case_sensitive - Looks for an exact match. Ignored by non-text columns (+true+ by default). + # * :case_sensitive - Set to true to look for an exact match or false to look for a + # case insensitive match. Can also be set to :db to use the databases case-sensitivity mode for the column. + # Ignored by non-text columns (+true+ by default). # * :allow_nil - If set to true, skips this validation if the attribute is +nil+ (default is +false+). # * :allow_blank - If set to true, skips this validation if the attribute is blank (default is +false+). # * :if - Specifies a method, proc or string to call to determine if the validation should @@ -725,7 +727,12 @@ module ActiveRecord if value.nil? comparison_operator = "IS ?" elsif column.text? - comparison_operator = "#{connection.case_sensitive_equality_operator} ?" + if configuration[:case_sensitive] == :db + comparison_operator = "= ?" + else + comparison_operator = "#{connection.case_sensitive_equality_operator} ?" + end + value = column.limit ? value.to_s[0, column.limit] : value.to_s else comparison_operator = "= ?" diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index c20f5ae..e819b6a 100644 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -496,6 +496,24 @@ class ValidationsTest < ActiveRecord::TestCase assert_not_equal "has already been taken", t3.errors.on(:title) end + def test_validate_db_case_sensitive_uniqueness + Topic.validates_uniqueness_of(:title, :case_sensitive => :db, :allow_nil => true) + + t = Topic.new(:title => "I'm unique!") + assert t.save, "Should save t" + + db_case_insensitive = Topic.find_all_by_id_and_title(t.id, "I'm UNIQUE!").any? + + t2 = Topic.new(:title => db_case_insensitive ? "I'm UNIQUE!" : "I'm unique!") + assert !t2.valid?, "Shouldn't be valid" + assert !t2.save, "Shouldn't save t2 as unique" + assert t2.errors[:title].any?, "Should be errors for title" + assert_equal "has already been taken", t2.errors[:title] + + t3 = Topic.new(:title => db_case_insensitive ? "I'm truly UNIQUE!" : "I'm UNIQUE!") + assert t3.save, "Should save t3" + end + def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer Topic.validates_uniqueness_of(:title, :case_sensitve => true) t = Topic.create!('title' => 101) -- 1.6.3.3