diff --git a/activerecord/lib/active_record/association_relation.rb b/activerecord/lib/active_record/association_relation.rb index 7418e28b21267..91c2df8465afc 100644 --- a/activerecord/lib/active_record/association_relation.rb +++ b/activerecord/lib/active_record/association_relation.rb @@ -15,20 +15,26 @@ def ==(other) other == records end - def build(*args, &block) + def build(attributes = nil, &block) block = _deprecated_scope_block("new", &block) - scoping { @association.build(*args, &block) } + @association.enable_scoping do + scoping { @association.build(attributes, &block) } + end end alias new build - def create(*args, &block) + def create(attributes = nil, &block) block = _deprecated_scope_block("create", &block) - scoping { @association.create(*args, &block) } + @association.enable_scoping do + scoping { @association.create(attributes, &block) } + end end - def create!(*args, &block) + def create!(attributes = nil, &block) block = _deprecated_scope_block("create!", &block) - scoping { @association.create!(*args, &block) } + @association.enable_scoping do + scoping { @association.create!(attributes, &block) } + end end private diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index 705a5571eedd3..c826571a18f79 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -43,6 +43,7 @@ def initialize(owner, reflection) reflection.check_validity! @owner, @reflection = owner, reflection + @enable_scoping = false reset reset_scope @@ -199,6 +200,13 @@ def create!(attributes = {}, &block) _create_record(attributes, true, &block) end + def enable_scoping + @enable_scoping = true + yield + ensure + @enable_scoping = false + end + private def find_target scope = self.scope @@ -229,7 +237,11 @@ def association_scope # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the # through association's scope) def target_scope - AssociationRelation.create(klass, self).merge!(klass.scope_for_association) + AssociationRelation.create(klass, self).merge!(scope_for_association) + end + + def scope_for_association + @enable_scoping ? klass.all : klass.scope_for_association end def scope_for_create diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 9e5b686aed938..8e6008027b097 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -216,6 +216,9 @@ def test_create_from_association_should_respect_default_scope bulb = car.bulbs.create assert_equal "defaulty", bulb.name + + bulb = car.bulbs.create! + assert_equal "defaulty", bulb.name end def test_build_and_create_from_association_should_respect_passed_attributes_over_default_scope @@ -227,11 +230,30 @@ def test_build_and_create_from_association_should_respect_passed_attributes_over bulb = car.bulbs.create(name: "exotic") assert_equal "exotic", bulb.name + bulb = car.bulbs.create!(name: "exotic") + assert_equal "exotic", bulb.name + bulb = car.awesome_bulbs.build(frickinawesome: false) assert_equal false, bulb.frickinawesome bulb = car.awesome_bulbs.create(frickinawesome: false) assert_equal false, bulb.frickinawesome + + bulb = car.awesome_bulbs.create!(frickinawesome: false) + assert_equal false, bulb.frickinawesome + end + + def test_build_and_create_from_association_should_respect_unscope_over_default_scope + car = Car.create(name: "honda") + + bulb = car.bulbs.unscope(where: :name).build + assert_nil bulb.name + + bulb = car.bulbs.unscope(where: :name).create + assert_nil bulb.name + + bulb = car.bulbs.unscope(where: :name).create! + assert_nil bulb.name end def test_build_from_association_should_respect_scope @@ -2504,6 +2526,7 @@ def test_association_with_rewhere_doesnt_set_inverse_instance_key assert_equal 0, Client.count end end + assert_equal "lol", client.name assert_equal [client], firm.clients_of_firm end @@ -2515,6 +2538,7 @@ def test_association_with_rewhere_doesnt_set_inverse_instance_key assert_equal 0, Client.count end end + assert_equal "lol", client.name assert_equal [client], firm.clients_of_firm assert_equal [client], firm.reload.clients_of_firm end @@ -2527,6 +2551,7 @@ def test_association_with_rewhere_doesnt_set_inverse_instance_key assert_equal 0, Client.count end end + assert_equal "lol", client.name assert_equal [client], firm.clients_of_firm assert_equal [client], firm.reload.clients_of_firm end