mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Fix scope_for_create
to take only equality nodes
Related #39683. If a scope has IN cluase, `scope_for_create` which is passed to `assign_attributes` will include array values, and it will cause weird behaviors. That behavior was due to the `In` node was a subclass of the `Equality` node (now the checking has migrated to `equality?` method). i.e. It works unless IN queries, for example (BETWEEN): ```ruby user = User.where(role: 0..1).find_or_initialize_by(name: "name") ``` I think that the `In` node was a subclass of the `Equality` node is accidental, so the behavior is almost a bug to me. This makes `scope_for_create` takes only equality nodes to fix the issue. Fixes #41295.
This commit is contained in:
parent
5268006e70
commit
82a6bd7c89
3 changed files with 26 additions and 7 deletions
|
@ -683,8 +683,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def scope_for_create
|
||||
hash = where_values_hash
|
||||
hash.delete(klass.inheritance_column) if klass.finder_needs_type_condition?
|
||||
hash = where_clause.to_h(klass.table_name, equality_only: true)
|
||||
create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
|
||||
hash
|
||||
end
|
||||
|
|
|
@ -58,8 +58,8 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
def to_h(table_name = nil)
|
||||
equalities(predicates).each_with_object({}) do |node, hash|
|
||||
def to_h(table_name = nil, equality_only: false)
|
||||
equalities(predicates, equality_only).each_with_object({}) do |node, hash|
|
||||
next if table_name&.!= node.left.relation.name
|
||||
name = node.left.name.to_s
|
||||
value = extract_node_value(node.right)
|
||||
|
@ -134,14 +134,14 @@ module ActiveRecord
|
|||
attr_node
|
||||
end
|
||||
|
||||
def equalities(predicates)
|
||||
def equalities(predicates, equality_only)
|
||||
equalities = []
|
||||
|
||||
predicates.each do |node|
|
||||
if equality_node?(node)
|
||||
if equality_only ? Arel::Nodes::Equality === node : equality_node?(node)
|
||||
equalities << node
|
||||
elsif node.is_a?(Arel::Nodes::And)
|
||||
equalities.concat equalities(node.children)
|
||||
equalities.concat equalities(node.children, equality_only)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -212,6 +212,26 @@ class RelationScopingTest < ActiveRecord::TestCase
|
|||
assert_includes Post.find(1).comments, new_comment
|
||||
end
|
||||
|
||||
def test_scoped_create_with_where_with_array
|
||||
new_comment = VerySpecialComment.where(label: [0, 1], post_id: 1).scoping do
|
||||
VerySpecialComment.create body: "Wonderful world"
|
||||
end
|
||||
|
||||
assert_equal 1, new_comment.post_id
|
||||
assert_equal "default", new_comment.label
|
||||
assert_includes Post.find(1).comments, new_comment
|
||||
end
|
||||
|
||||
def test_scoped_create_with_where_with_range
|
||||
new_comment = VerySpecialComment.where(label: 0..1, post_id: 1).scoping do
|
||||
VerySpecialComment.create body: "Wonderful world"
|
||||
end
|
||||
|
||||
assert_equal 1, new_comment.post_id
|
||||
assert_equal "default", new_comment.label
|
||||
assert_includes Post.find(1).comments, new_comment
|
||||
end
|
||||
|
||||
def test_scoped_create_with_create_with
|
||||
new_comment = VerySpecialComment.create_with(post_id: 1).scoping do
|
||||
VerySpecialComment.create body: "Wonderful world"
|
||||
|
|
Loading…
Reference in a new issue