From 5f521cbff3c8a46cfc8e16b234294a20c285d00d Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 26 Dec 2014 16:28:36 -0700 Subject: [PATCH] Go through normal `where` logic in uniqueness validation This code could use some much heavier refactoring. It looks like `build_relation` duplicates most of the logic of `Relation#where` and `PredicateBuilder` with regards to handling associations and attribute aliases --- .../lib/active_record/validations/uniqueness.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 255063e951..c4ff2e3ef3 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -16,9 +16,8 @@ module ActiveRecord value = map_enum_attribute(finder_class, attribute, value) relation = build_relation(finder_class, table, attribute, value) - relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted? + relation = relation.where.not(finder_class.primary_key => record.id) if record.persisted? relation = scope_relation(record, table, relation) - relation = finder_class.unscoped.where(relation) relation = relation.merge(options[:conditions]) if options[:conditions] if relation.exists? @@ -65,13 +64,16 @@ module ActiveRecord value = value.to_s[0, column.limit] end + # FIXME: Remove this when type casting is removed from Arel (Rails 5.1) value = Arel::Nodes::Quoted.new(value) - if !options[:case_sensitive] && value && column.text? + + comparison = if !options[:case_sensitive] && value && column.text? # will use SQL LOWER function before comparison, unless it detects a case insensitive collation klass.connection.case_insensitive_comparison(table, attribute, column, value) else klass.connection.case_sensitive_comparison(table, attribute, column, value) end + klass.unscoped.where(comparison) end def scope_relation(record, table, relation) @@ -82,7 +84,7 @@ module ActiveRecord else scope_value = record._read_attribute(scope_item) end - relation = relation.and(table[scope_item].eq(scope_value)) + relation = relation.where(scope_item => scope_value) end relation