aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/where_clause.rb
diff options
context:
space:
mode:
authorSean Griffin <sean@thoughtbot.com>2015-01-25 15:27:43 -0700
committerSean Griffin <sean@thoughtbot.com>2015-01-25 16:31:21 -0700
commitdef2879d7d187df945d77c1028d4cef588cbc8a0 (patch)
tree29325310fe304bbfe52a6b2811b803b8a1c1ae6a /activerecord/lib/active_record/relation/where_clause.rb
parent2c46d6db4feaf4284415f2fb6ceceb1bb535f278 (diff)
downloadrails-def2879d7d187df945d77c1028d4cef588cbc8a0.tar.gz
rails-def2879d7d187df945d77c1028d4cef588cbc8a0.tar.bz2
rails-def2879d7d187df945d77c1028d4cef588cbc8a0.zip
Move where merging logic over to `WhereClause`
This object being a black box, it knows the details of how to merge itself with another where clause. This removes all references to where values or bind values in `Relation::Merger`
Diffstat (limited to 'activerecord/lib/active_record/relation/where_clause.rb')
-rw-r--r--activerecord/lib/active_record/relation/where_clause.rb36
1 files changed, 35 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/relation/where_clause.rb b/activerecord/lib/active_record/relation/where_clause.rb
index b39fc1fed1..cd6da052a9 100644
--- a/activerecord/lib/active_record/relation/where_clause.rb
+++ b/activerecord/lib/active_record/relation/where_clause.rb
@@ -1,6 +1,6 @@
module ActiveRecord
class Relation
- class WhereClause
+ class WhereClause # :nodoc:
attr_reader :parts, :binds
def initialize(parts, binds)
@@ -15,6 +15,13 @@ module ActiveRecord
)
end
+ def merge(other)
+ WhereClause.new(
+ parts_unreferenced_by(other) + other.parts,
+ non_conflicting_binds(other) + other.binds,
+ )
+ end
+
def ==(other)
other.is_a?(WhereClause) &&
parts == other.parts &&
@@ -24,6 +31,33 @@ module ActiveRecord
def self.empty
new([], [])
end
+
+ protected
+
+ def referenced_columns
+ @referenced_columns ||= begin
+ equality_nodes = parts.select { |n| equality_node?(n) }
+ Set.new(equality_nodes, &:left)
+ end
+ end
+
+ private
+
+ def parts_unreferenced_by(other)
+ parts.reject do |n|
+ equality_node?(n) && other.referenced_columns.include?(n.left)
+ end
+ end
+
+ def equality_node?(node)
+ node.respond_to?(:operator) && node.operator == :==
+ end
+
+ def non_conflicting_binds(other)
+ conflicts = referenced_columns & other.referenced_columns
+ conflicts.map! { |node| node.name.to_s }
+ binds.reject { |col, _| conflicts.include?(col.name) }
+ end
end
end
end