diff options
author | Sean Griffin <sean@thoughtbot.com> | 2015-01-25 15:27:43 -0700 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2015-01-25 16:31:21 -0700 |
commit | def2879d7d187df945d77c1028d4cef588cbc8a0 (patch) | |
tree | 29325310fe304bbfe52a6b2811b803b8a1c1ae6a /activerecord/lib/active_record/relation/where_clause.rb | |
parent | 2c46d6db4feaf4284415f2fb6ceceb1bb535f278 (diff) | |
download | rails-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.rb | 36 |
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 |