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

Allow extra scoping in callbacks when create on association relation

#37523 has a regression that ignore extra scoping in callbacks when
create on association relation.

It should respect `klass.current_scope` even when create on association
relation to allow extra scoping in callbacks.

Fixes #38741.
This commit is contained in:
Ryuta Kamizono 2020-03-21 23:10:34 +09:00
parent 8544c9c236
commit f64b5fb942
4 changed files with 28 additions and 19 deletions

View file

@ -17,24 +17,18 @@ module ActiveRecord
def build(attributes = nil, &block) def build(attributes = nil, &block)
block = _deprecated_scope_block("new", &block) block = _deprecated_scope_block("new", &block)
@association.scoping(self) do scoping { @association.build(attributes, &block) }
@association.build(attributes, &block)
end
end end
alias new build alias new build
def create(attributes = nil, &block) def create(attributes = nil, &block)
block = _deprecated_scope_block("create", &block) block = _deprecated_scope_block("create", &block)
@association.scoping(self) do scoping { @association.create(attributes, &block) }
@association.create(attributes, &block)
end
end end
def create!(attributes = nil, &block) def create!(attributes = nil, &block)
block = _deprecated_scope_block("create!", &block) block = _deprecated_scope_block("create!", &block)
@association.scoping(self) do scoping { @association.create!(attributes, &block) }
@association.create!(attributes, &block)
end
end end
private private

View file

@ -41,7 +41,6 @@ module ActiveRecord
reflection.check_validity! reflection.check_validity!
@owner, @reflection = owner, reflection @owner, @reflection = owner, reflection
@_scope = nil
reset reset
reset_scope reset_scope
@ -98,7 +97,11 @@ module ActiveRecord
end end
def scope def scope
@_scope&.spawn || target_scope.merge!(association_scope) if (scope = klass.current_scope) && scope.try(:proxy_association) == self
scope.spawn
else
target_scope.merge!(association_scope)
end
end end
def reset_scope def reset_scope
@ -198,13 +201,6 @@ module ActiveRecord
_create_record(attributes, true, &block) _create_record(attributes, true, &block)
end end
def scoping(relation, &block)
@_scope = relation
relation.scoping(&block)
ensure
@_scope = nil
end
private private
def find_target def find_target
if owner.strict_loading? if owner.strict_loading?

View file

@ -224,6 +224,18 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_build_and_create_from_association_should_respect_passed_attributes_over_default_scope def test_build_and_create_from_association_should_respect_passed_attributes_over_default_scope
car = Car.create(name: "honda") car = Car.create(name: "honda")
bulb = car.bulbs.where(name: "exotic").build
assert_equal "exotic", bulb.name
assert_nil bulb.count_after_create
bulb = car.bulbs.where(name: "exotic").create
assert_equal "exotic", bulb.name
assert_equal 1, bulb.count_after_create
bulb = car.bulbs.where(name: "exotic").create!
assert_equal "exotic", bulb.name
assert_equal 2, bulb.count_after_create
bulb = car.bulbs.build(name: "exotic") bulb = car.bulbs.build(name: "exotic")
assert_equal "exotic", bulb.name assert_equal "exotic", bulb.name

View file

@ -5,7 +5,7 @@ class Bulb < ActiveRecord::Base
belongs_to :car, touch: true belongs_to :car, touch: true
scope :awesome, -> { where(frickinawesome: true) } scope :awesome, -> { where(frickinawesome: true) }
attr_reader :scope_after_initialize, :attributes_after_initialize attr_reader :scope_after_initialize, :attributes_after_initialize, :count_after_create
after_initialize :record_scope_after_initialize after_initialize :record_scope_after_initialize
def record_scope_after_initialize def record_scope_after_initialize
@ -17,6 +17,13 @@ class Bulb < ActiveRecord::Base
@attributes_after_initialize = attributes.dup @attributes_after_initialize = attributes.dup
end end
after_create :record_count_after_create
def record_count_after_create
@count_after_create = Bulb.unscoped do
car&.bulbs&.count
end
end
def color=(color) def color=(color)
self[:color] = color.upcase + "!" self[:color] = color.upcase + "!"
end end