aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRafael Mendonça França <rafaelmfranca@gmail.com>2016-08-17 00:00:54 -0300
committerRafael Mendonça França <rafaelmfranca@gmail.com>2016-08-17 00:00:54 -0300
commit7eec1ba60483e22fb1dfd69f821cbb7a48ef6ff9 (patch)
treee5aed02f8158cbaeb82d4f40a2fca706995a9009 /activerecord
parent2af63c9c9f44028ca6c3a418756c1d0a783c12c5 (diff)
parent3a1f6fe7b4a70bf0698b0684dd48ac712c6883b6 (diff)
downloadrails-7eec1ba60483e22fb1dfd69f821cbb7a48ef6ff9.tar.gz
rails-7eec1ba60483e22fb1dfd69f821cbb7a48ef6ff9.tar.bz2
rails-7eec1ba60483e22fb1dfd69f821cbb7a48ef6ff9.zip
Merge pull request #26072 from kamipo/extract_case_sensitive_handler
Extract `PredicateBuilder::CaseSensitiveHandler`
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb12
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb7
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb28
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/case_sensitive_handler.rb21
-rw-r--r--activerecord/lib/active_record/relation/where_clause_factory.rb2
-rw-r--r--activerecord/lib/active_record/validations/uniqueness.rb32
6 files changed, 51 insertions, 51 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 0c7197a002..4dde525ebc 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -433,16 +433,16 @@ module ActiveRecord
@connection
end
- def case_sensitive_comparison(table, attribute, column, value)
- table[attribute].eq(Arel::Nodes::BindParam.new)
+ def case_sensitive_comparison(attribute, column, value) # :nodoc:
+ attribute.eq(value)
end
- def case_insensitive_comparison(table, attribute, column, value)
+ def case_insensitive_comparison(attribute, column, value) # :nodoc:
if can_perform_case_insensitive_comparison_for?(column)
- table[attribute].lower.eq(table.lower(Arel::Nodes::BindParam.new))
- else
- table[attribute].eq(Arel::Nodes::BindParam.new)
+ value = attribute.relation.lower(value)
+ attribute = attribute.lower
end
+ attribute.eq(value)
end
def can_perform_case_insensitive_comparison_for?(column)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 5900919e88..e7efc4caf7 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -613,12 +613,11 @@ module ActiveRecord
SQL
end
- def case_sensitive_comparison(table, attribute, column, value)
+ def case_sensitive_comparison(attribute, column, value) # :nodoc:
if column.collation && !column.case_sensitive?
- table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
- else
- super
+ value = Arel::Nodes::Bin.new(value)
end
+ attribute.eq(value)
end
def can_perform_case_insensitive_comparison_for?(column)
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 780a1ee422..29422bf131 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -4,6 +4,7 @@ module ActiveRecord
require "active_record/relation/predicate_builder/association_query_handler"
require "active_record/relation/predicate_builder/base_handler"
require "active_record/relation/predicate_builder/basic_object_handler"
+ require "active_record/relation/predicate_builder/case_sensitive_handler"
require "active_record/relation/predicate_builder/class_handler"
require "active_record/relation/predicate_builder/polymorphic_array_handler"
require "active_record/relation/predicate_builder/range_handler"
@@ -16,6 +17,7 @@ module ActiveRecord
@handlers = []
register_handler(BasicObject, BasicObjectHandler.new)
+ register_handler(CaseSensitiveHandler::Value, CaseSensitiveHandler.new)
register_handler(Class, ClassHandler.new(self))
register_handler(Base, BaseHandler.new(self))
register_handler(Range, RangeHandler.new)
@@ -31,9 +33,9 @@ module ActiveRecord
expand_from_hash(attributes)
end
- def create_binds(attributes)
+ def create_binds(attributes, options)
attributes = convert_dot_notation_to_hash(attributes)
- create_binds_for_hash(attributes)
+ create_binds_for_hash(attributes, options)
end
def self.references(attributes)
@@ -82,14 +84,14 @@ module ActiveRecord
end
end
- def create_binds_for_hash(attributes)
+ def create_binds_for_hash(attributes, options)
result = attributes.dup
binds = []
attributes.each do |column_name, value|
case
when value.is_a?(Hash) && !table.has_column?(column_name)
- attrs, bvs = associated_predicate_builder(column_name).create_binds_for_hash(value)
+ attrs, bvs = associated_predicate_builder(column_name).create_binds_for_hash(value, options)
result[column_name] = attrs
binds += bvs
next
@@ -108,11 +110,15 @@ module ActiveRecord
end
result[column_name] = RangeHandler::RangeWithBinds.new(first, last, value.exclude_end?)
- else
- if can_be_bound?(column_name, value)
- result[column_name] = Arel::Nodes::BindParam.new
- binds << build_bind_param(column_name, value)
- end
+ when can_be_bound?(column_name, value)
+ result[column_name] =
+ if perform_case_sensitive?(options)
+ CaseSensitiveHandler::Value.new(
+ Arel::Nodes::BindParam.new, table, options[:case_sensitive])
+ else
+ Arel::Nodes::BindParam.new
+ end
+ binds << build_bind_param(column_name, value)
end
# Find the foreign key when using queries such as:
@@ -164,6 +170,10 @@ module ActiveRecord
end
end
+ def perform_case_sensitive?(options)
+ options.key?(:case_sensitive)
+ end
+
def build_bind_param(column_name, value)
Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
end
diff --git a/activerecord/lib/active_record/relation/predicate_builder/case_sensitive_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/case_sensitive_handler.rb
new file mode 100644
index 0000000000..acf0bbd829
--- /dev/null
+++ b/activerecord/lib/active_record/relation/predicate_builder/case_sensitive_handler.rb
@@ -0,0 +1,21 @@
+module ActiveRecord
+ class PredicateBuilder
+ class CaseSensitiveHandler # :nodoc:
+ def call(attribute, value)
+ value.call(attribute)
+ end
+
+ class Value < Struct.new(:value, :table, :case_sensitive?) # :nodoc:
+ def call(attribute)
+ klass = table.send(:klass)
+ column = klass.column_for_attribute(attribute.name)
+ if case_sensitive?
+ klass.connection.case_sensitive_comparison(attribute, column, value)
+ else
+ klass.connection.case_insensitive_comparison(attribute, column, value)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb
index dc00149130..122ab04c00 100644
--- a/activerecord/lib/active_record/relation/where_clause_factory.rb
+++ b/activerecord/lib/active_record/relation/where_clause_factory.rb
@@ -17,7 +17,7 @@ module ActiveRecord
attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes)
attributes.stringify_keys!
- attributes, binds = predicate_builder.create_binds(attributes)
+ attributes, binds = predicate_builder.create_binds(attributes, other.last || {})
parts = predicate_builder.build_from_hash(attributes)
when Arel::Nodes::Node
diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb
index 8c4930a81d..08c4b01439 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -50,37 +50,7 @@ module ActiveRecord
end
def build_relation(klass, attribute, value) # :nodoc:
- if reflection = klass._reflect_on_association(attribute)
- attribute = reflection.foreign_key
- value = value.attributes[reflection.klass.primary_key] unless value.nil?
- end
-
- if value.nil?
- return klass.unscoped.where!(attribute => value)
- end
-
- # the attribute may be an aliased attribute
- if klass.attribute_alias?(attribute)
- attribute = klass.attribute_alias(attribute)
- end
-
- attribute_name = attribute.to_s
-
- table = klass.arel_table
- column = klass.columns_hash[attribute_name]
- cast_type = klass.type_for_attribute(attribute_name)
-
- comparison = if !options[:case_sensitive]
- # 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.tap do |scope|
- parts = [comparison]
- binds = [Relation::QueryAttribute.new(attribute_name, value, cast_type)]
- scope.where_clause += Relation::WhereClause.new(parts, binds)
- end
+ klass.unscoped.where!({ attribute => value }, options)
end
def scope_relation(record, relation)