diff options
Diffstat (limited to 'activerecord/lib/active_record/relation/spawn_methods.rb')
-rw-r--r-- | activerecord/lib/active_record/relation/spawn_methods.rb | 93 |
1 files changed, 17 insertions, 76 deletions
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 19ec41e5ca..a365b5723b 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -1,81 +1,24 @@ require 'active_support/core_ext/object/blank' +require 'active_record/relation/merger' module ActiveRecord module SpawnMethods - def merge(r) - return self unless r - return to_a & r if r.is_a?(Array) - - merged_relation = clone - - r = r.with_default_scope if r.default_scoped? && r.klass != klass - - Relation::ASSOCIATION_METHODS.each do |method| - value = r.send(:"#{method}_values") - - unless value.empty? - if method == :includes - merged_relation = merged_relation.includes(value) - else - merged_relation.send(:"#{method}_values=", value) - end - end - end - - (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order, :binds]).each do |method| - value = r.send(:"#{method}_values") - next if value.empty? - - value += merged_relation.send(:"#{method}_values") - merged_relation.send :"#{method}_values=", value - end - - merged_relation.joins_values += r.joins_values - - merged_wheres = @where_values + r.where_values - - merged_binds = (@bind_values + r.bind_values).uniq(&:first) - - unless @where_values.empty? - # Remove duplicates, last one wins. - seen = Hash.new { |h,table| h[table] = {} } - merged_wheres = merged_wheres.reverse.reject { |w| - nuke = false - if w.respond_to?(:operator) && w.operator == :== - name = w.left.name - table = w.left.relation.name - nuke = seen[table][name] - seen[table][name] = true - end - nuke - }.reverse - end - - merged_relation.where_values = merged_wheres - merged_relation.bind_values = merged_binds - - (Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method| - value = r.send(:"#{method}_value") - merged_relation.send(:"#{method}_value=", value) unless value.nil? + def merge(other) + if other.is_a?(Array) + to_a & other + elsif other + clone.merge!(other) + else + self end + end - merged_relation.lock_value = r.lock_value unless merged_relation.lock_value - - merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty? - - if (r.reordering_value) - # override any order specified in the original relation - merged_relation.reordering_value = true - merged_relation.order_values = r.order_values + def merge!(other) + if other.is_a?(Hash) + Relation::HashMerger.new(self, other).merge else - # merge in order_values from r - merged_relation.order_values += r.order_values + Relation::Merger.new(self, other).merge end - - # Apply scope extension modules - merged_relation.send :apply_modules, r.extensions - - merged_relation end # Removes from the query the condition(s) specified in +skips+. @@ -89,7 +32,7 @@ module ActiveRecord result = self.class.new(@klass, table) result.default_scoped = default_scoped - ((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) - skips).each do |method| + (Relation::MULTI_VALUE_METHODS - skips).each do |method| result.send(:"#{method}_values=", send(:"#{method}_values")) end @@ -97,8 +40,7 @@ module ActiveRecord result.send(:"#{method}_value=", send(:"#{method}_value")) end - # Apply scope extension modules - result.send(:apply_modules, extensions) + result.extend(*extending_values) if extending_values.any? result end @@ -114,7 +56,7 @@ module ActiveRecord result = self.class.new(@klass, table) result.default_scoped = default_scoped - ((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) & onlies).each do |method| + (Relation::MULTI_VALUE_METHODS & onlies).each do |method| result.send(:"#{method}_values=", send(:"#{method}_values")) end @@ -122,8 +64,7 @@ module ActiveRecord result.send(:"#{method}_value=", send(:"#{method}_value")) end - # Apply scope extension modules - result.send(:apply_modules, extensions) + result.extend(*extending_values) if extending_values.any? result end |