From ef1d1e1492e3c48884f7653103bc9313dd04cfad Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 22 Apr 2012 11:34:55 +0200 Subject: fix interpolation for hash merging --- activerecord/lib/active_record/relation/merger.rb | 39 +++++++++++++--------- .../lib/active_record/relation/spawn_methods.rb | 7 ++-- 2 files changed, 26 insertions(+), 20 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb index 52cf0b7077..3f880ce5e9 100644 --- a/activerecord/lib/active_record/relation/merger.rb +++ b/activerecord/lib/active_record/relation/merger.rb @@ -3,32 +3,41 @@ require 'active_support/core_ext/hash/keys' module ActiveRecord class Relation - class Merger - attr_reader :relation, :other + class HashMerger + attr_reader :relation, :hash - def initialize(relation, other) - @relation = relation + def initialize(relation, hash) + hash.assert_valid_keys(*Relation::VALUE_METHODS) - if other.default_scoped? && other.klass != relation.klass - @other = other.with_default_scope - else - @other = other - end + @relation = relation + @hash = hash end def merge - HashMerger.new(relation, other.values).merge + Merger.new(relation, other).merge + end + + # Applying values to a relation has some side effects. E.g. + # interpolation might take place for where values. So we should + # build a relation to merge in rather than directly merging + # the values. + def other + other = Relation.new(relation.klass, relation.table) + hash.each { |k, v| other.send("#{k}!", v) } + other end end - class HashMerger + class Merger attr_reader :relation, :values - def initialize(relation, values) - values.assert_valid_keys(*Relation::VALUE_METHODS) + def initialize(relation, other) + if other.default_scoped? && other.klass != relation.klass + other = other.with_default_scope + end @relation = relation - @values = values + @values = other.values end def normal_values @@ -85,7 +94,7 @@ module ActiveRecord def merged_wheres if values[:where] - merged_wheres = relation.where_values + Array(values[:where]) + merged_wheres = relation.where_values + values[:where] unless relation.where_values.empty? # Remove duplicates, last one wins. diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 1d2151fdb2..41e55dfd0e 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -30,11 +30,8 @@ module ActiveRecord end def merge!(other) - if other.is_a?(Hash) - Relation::HashMerger.new(self, other).merge - else - Relation::Merger.new(self, other).merge - end + klass = other.is_a?(Hash) ? Relation::HashMerger : Relation::Merger + klass.new(self, other).merge end # Removes from the query the condition(s) specified in +skips+. -- cgit v1.2.3