aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/relation/merger.rb39
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb7
-rw-r--r--activerecord/test/cases/relation_test.rb17
3 files changed, 39 insertions, 24 deletions
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+.
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index d1fb3e01d2..8a7a2441d4 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -130,9 +130,9 @@ module ActiveRecord
test 'merging a hash into a relation' do
relation = Relation.new :a, :b
- relation = relation.merge where: ['lol'], readonly: true
+ relation = relation.merge where: :lol, readonly: true
- assert_equal ['lol'], relation.where_values
+ assert_equal [:lol], relation.where_values
assert_equal true, relation.readonly_value
end
@@ -162,6 +162,15 @@ module ActiveRecord
relation.merge!(where: :foo)
assert_equal [:foo], relation.where_values
end
+
+ test 'merging a hash interpolates conditions' do
+ klass = stub
+ klass.stubs(:sanitize_sql).with(['foo = ?', 'bar']).returns('foo = bar')
+
+ relation = Relation.new(klass, :b)
+ relation.merge!(where: ['foo = ?', 'bar'])
+ assert_equal ['foo = bar'], relation.where_values
+ end
end
class RelationMutationTest < ActiveSupport::TestCase
@@ -227,8 +236,8 @@ module ActiveRecord
end
test 'merge!' do
- assert relation.merge!(where: ['foo']).equal?(relation)
- assert_equal ['foo'], relation.where_values
+ assert relation.merge!(where: :foo).equal?(relation)
+ assert_equal [:foo], relation.where_values
end
end
end