aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2017-07-13 07:14:59 +0900
committerRyuta Kamizono <kamipo@gmail.com>2017-07-16 15:38:49 +0900
commit01c85097d4977b0c141b7c89df15c0750f37c62d (patch)
tree301350f925e10f533c75923585a0f84d99828897 /activerecord
parent189b8a06dc703f7a8477f877f0a02e23dd691ed8 (diff)
downloadrails-01c85097d4977b0c141b7c89df15c0750f37c62d.tar.gz
rails-01c85097d4977b0c141b7c89df15c0750f37c62d.tar.bz2
rails-01c85097d4977b0c141b7c89df15c0750f37c62d.zip
Fix `create_with` using both string and symbol
This is related with #27680. Since `where_values_hash` keys constructed by `where` are string, so we need `stringify_keys` to `create_with_value` before merging it.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/association.rb7
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb4
-rw-r--r--activerecord/lib/active_record/associations/singular_association.rb5
-rw-r--r--activerecord/lib/active_record/relation.rb2
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb2
-rw-r--r--activerecord/lib/active_record/relation/where_clause.rb4
-rw-r--r--activerecord/test/cases/relation_test.rb7
-rw-r--r--activerecord/test/cases/relations_test.rb2
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb5
9 files changed, 20 insertions, 18 deletions
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index 1138ae3462..6acf831759 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -171,8 +171,8 @@ module ActiveRecord
skip_assign = [reflection.foreign_key, reflection.type].compact
assigned_keys = record.changed_attribute_names_to_save
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
- attributes = create_scope.except(*(assigned_keys - skip_assign))
- record.assign_attributes(attributes)
+ attributes = scope_for_create.except(*(assigned_keys - skip_assign))
+ record.send(:_assign_attributes, attributes) if attributes.any?
set_inverse_instance(record)
end
@@ -185,6 +185,9 @@ module ActiveRecord
end
private
+ def scope_for_create
+ scope.scope_for_create
+ end
def find_target?
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index a49fb155ee..69401162aa 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -374,10 +374,6 @@ module ActiveRecord
end
end
- def create_scope
- scope.scope_for_create.stringify_keys
- end
-
def delete_or_destroy(records, method)
records = records.flatten
records.each { |record| raise_on_type_mismatch!(record) }
diff --git a/activerecord/lib/active_record/associations/singular_association.rb b/activerecord/lib/active_record/associations/singular_association.rb
index f8bbe4c2ed..4896afcca7 100644
--- a/activerecord/lib/active_record/associations/singular_association.rb
+++ b/activerecord/lib/active_record/associations/singular_association.rb
@@ -30,9 +30,8 @@ module ActiveRecord
end
private
-
- def create_scope
- scope.scope_for_create.stringify_keys.except(klass.primary_key)
+ def scope_for_create
+ super.except(klass.primary_key)
end
def find_target
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 76cf47a3ed..82018436a0 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -591,7 +591,7 @@ module ActiveRecord
end
def scope_for_create
- @scope_for_create ||= where_values_hash.merge(create_with_value)
+ @scope_for_create ||= where_values_hash.merge!(create_with_value.stringify_keys)
end
# Returns true if relation needs eager loading.
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 79495ead91..9d6db3dc64 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -797,7 +797,7 @@ module ActiveRecord
value = sanitize_forbidden_attributes(value)
self.create_with_value = create_with_value.merge(value)
else
- self.create_with_value = {}
+ self.create_with_value = FROZEN_EMPTY_HASH
end
self
diff --git a/activerecord/lib/active_record/relation/where_clause.rb b/activerecord/lib/active_record/relation/where_clause.rb
index 119910ee79..0feb2c6cb2 100644
--- a/activerecord/lib/active_record/relation/where_clause.rb
+++ b/activerecord/lib/active_record/relation/where_clause.rb
@@ -52,8 +52,8 @@ module ActiveRecord
binds = self.binds.map { |attr| [attr.name, attr.value] }.to_h
equalities.map { |node|
- name = node.left.name
- [name, binds.fetch(name.to_s) {
+ name = node.left.name.to_s
+ [name, binds.fetch(name) {
case node.right
when Array then node.right.map(&:val)
when Arel::Nodes::Casted, Arel::Nodes::Quoted
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 9bc7c9f949..d2859cbafd 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -83,16 +83,15 @@ module ActiveRecord
def test_create_with_value
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
- hash = { hello: "world" }
- relation.create_with_value = hash
- assert_equal hash, relation.scope_for_create
+ relation.create_with_value = { hello: "world" }
+ assert_equal({ "hello" => "world" }, relation.scope_for_create)
end
def test_create_with_value_with_wheres
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
relation.where!(id: 10)
relation.create_with_value = { hello: "world" }
- assert_equal({ hello: "world", "id" => 10 }, relation.scope_for_create)
+ assert_equal({ "hello" => "world", "id" => 10 }, relation.scope_for_create)
end
# FIXME: is this really wanted or expected behavior?
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index eb3449b331..6c35940c2e 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -1482,7 +1482,7 @@ class RelationTest < ActiveRecord::TestCase
assert_equal bird, Bird.find_or_initialize_by(name: "bob")
end
- def test_explicit_create_scope
+ def test_explicit_create_with
hens = Bird.where(name: "hen")
assert_equal "hen", hens.new.name
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index 89fb434b27..e310739f7b 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -342,6 +342,11 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal "Aaron", aaron.name
end
+ def test_create_with_using_both_string_and_symbol
+ jamis = PoorDeveloperCalledJamis.create_with(name: "foo").create_with("name" => "Aaron").new
+ assert_equal "Aaron", jamis.name
+ end
+
def test_create_with_reset
jamis = PoorDeveloperCalledJamis.create_with(name: "Aaron").create_with(nil).new
assert_equal "Jamis", jamis.name