1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Allow build multiple records even on non association relation

Follow up to #41342.

The reason why the problem of #41342 occurred is that unlike `create`,
`build` did not support the creation of multiple records, so it did not
address the problem.

It is weird that `post.commnets.where(foo: "bar").build([obj1, obj2])`
is allowed but `Comment.where(foo: "bar").build([obj1, obj2])` is not
allowed.

To avoid the confusion, it allows `build` multiple records even on non
association relation.
This commit is contained in:
Ryuta Kamizono 2021-02-08 21:34:11 +09:00
parent 6515d6985d
commit 66ec42946c
3 changed files with 34 additions and 12 deletions

View file

@ -27,16 +27,6 @@ module ActiveRecord
RUBY RUBY
end end
def build(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| build(attr, &block) }
else
block = current_scope_restoring_block(&block)
scoping { _new(attributes, &block) }
end
end
alias new build
private private
def _new(attributes, &block) def _new(attributes, &block)
@association.build(attributes, &block) @association.build(attributes, &block)

View file

@ -67,9 +67,13 @@ module ActiveRecord
# user = users.new { |user| user.name = 'Oscar' } # user = users.new { |user| user.name = 'Oscar' }
# user.name # => Oscar # user.name # => Oscar
def new(attributes = nil, &block) def new(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| new(attr, &block) }
else
block = current_scope_restoring_block(&block) block = current_scope_restoring_block(&block)
scoping { _new(attributes, &block) } scoping { _new(attributes, &block) }
end end
end
alias build new alias build new
# Tries to create a new record with the same scoped attributes # Tries to create a new record with the same scoped attributes

View file

@ -1278,6 +1278,34 @@ class RelationTest < ActiveRecord::TestCase
assert_equal post, comment.post assert_equal post, comment.post
end end
def test_new_with_array
green_birds = Bird.where(color: "green").new([{ name: "parrot" }, { name: "canary" }])
assert_equal ["parrot", "canary"], green_birds.map(&:name)
assert_equal ["green", "green"], green_birds.map(&:color)
green_birds.each { |bird| assert_not_predicate bird, :persisted? }
end
def test_build_with_array
green_birds = Bird.where(color: "green").build([{ name: "parrot" }, { name: "canary" }])
assert_equal ["parrot", "canary"], green_birds.map(&:name)
assert_equal ["green", "green"], green_birds.map(&:color)
green_birds.each { |bird| assert_not_predicate bird, :persisted? }
end
def test_create_with_array
green_birds = Bird.where(color: "green").create([{ name: "parrot" }, { name: "canary" }])
assert_equal ["parrot", "canary"], green_birds.map(&:name)
assert_equal ["green", "green"], green_birds.map(&:color)
green_birds.each { |bird| assert_predicate bird, :persisted? }
end
def test_create_bang_with_array
green_birds = Bird.where(color: "green").create!([{ name: "parrot" }, { name: "canary" }])
assert_equal ["parrot", "canary"], green_birds.map(&:name)
assert_equal ["green", "green"], green_birds.map(&:color)
green_birds.each { |bird| assert_predicate bird, :persisted? }
end
def test_first_or_create def test_first_or_create
parrot = Bird.where(color: "green").first_or_create(name: "parrot") parrot = Bird.where(color: "green").first_or_create(name: "parrot")
assert_kind_of Bird, parrot assert_kind_of Bird, parrot