From eeb5baa86f672021f18b59903a2090df407ab065 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 5 Feb 2021 18:59:02 +0900 Subject: [PATCH] Merge pull request #41342 from kamipo/fix_build_on_association_relation Fix `build` multiple records on association relation to not lose scope values --- .../lib/active_record/association_relation.rb | 10 ++++ .../has_many_associations_test.rb | 50 +++++++++++++++++-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/association_relation.rb b/activerecord/lib/active_record/association_relation.rb index 7bcefe71adbf1..41571857b3281 100644 --- a/activerecord/lib/active_record/association_relation.rb +++ b/activerecord/lib/active_record/association_relation.rb @@ -27,6 +27,16 @@ def #{method}(attributes, **kwargs) RUBY 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 def _new(attributes, &block) @association.build(attributes, &block) diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 9611de60e777e..0fa80319fe788 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -374,14 +374,58 @@ def test_building_the_associated_object_with_an_unrelated_type assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(type: "Account") } end - test "building the association with an array" do + test "build the association with an array" do speedometer = Speedometer.new(speedometer_id: "a") data = [{ name: "first" }, { name: "second" }] - speedometer.minivans.build(data) + speedometer.minivans.where(color: "blue").build(data) assert_equal 2, speedometer.minivans.size assert speedometer.save - assert_equal ["first", "second"], speedometer.reload.minivans.map(&:name) + + speedometer.reload + + assert_equal ["first", "second"], speedometer.minivans.map(&:name) + assert_equal ["blue", "blue"], speedometer.minivans.map(&:color) + end + + test "new the association with an array" do + speedometer = Speedometer.new(speedometer_id: "a") + data = [{ name: "first" }, { name: "second" }] + speedometer.minivans.where(color: "blue").new(data) + + assert_equal 2, speedometer.minivans.size + assert speedometer.save + + speedometer.reload + + assert_equal ["first", "second"], speedometer.minivans.map(&:name) + assert_equal ["blue", "blue"], speedometer.minivans.map(&:color) + end + + test "create the association with an array" do + speedometer = Speedometer.create!(speedometer_id: "a") + data = [{ name: "first" }, { name: "second" }] + speedometer.minivans.where(color: "blue").create(data) + + assert_equal 2, speedometer.minivans.size + + speedometer.reload + + assert_equal ["first", "second"], speedometer.minivans.map(&:name) + assert_equal ["blue", "blue"], speedometer.minivans.map(&:color) + end + + test "create! the association with an array" do + speedometer = Speedometer.create!(speedometer_id: "a") + data = [{ name: "first" }, { name: "second" }] + speedometer.minivans.where(color: "blue").create!(data) + + assert_equal 2, speedometer.minivans.size + + speedometer.reload + + assert_equal ["first", "second"], speedometer.minivans.map(&:name) + assert_equal ["blue", "blue"], speedometer.minivans.map(&:color) end def test_association_keys_bypass_attribute_protection