Skip to content

Commit ef10fc2

Browse files
committed
Merge pull request rails#37523 from kamipo/refactor_association_scoping
Refactor `association.scoping` not to rely on `klass.all`
1 parent bc5c2c0 commit ef10fc2

File tree

4 files changed

+25
-18
lines changed

4 files changed

+25
-18
lines changed

activerecord/lib/active_record/association_relation.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,23 @@ def ==(other)
1717

1818
def build(attributes = nil, &block)
1919
block = _deprecated_scope_block("new", &block)
20-
@association.enable_scoping do
21-
scoping { @association.build(attributes, &block) }
20+
@association.scoping(self) do
21+
@association.build(attributes, &block)
2222
end
2323
end
2424
alias new build
2525

2626
def create(attributes = nil, &block)
2727
block = _deprecated_scope_block("create", &block)
28-
@association.enable_scoping do
29-
scoping { @association.create(attributes, &block) }
28+
@association.scoping(self) do
29+
@association.create(attributes, &block)
3030
end
3131
end
3232

3333
def create!(attributes = nil, &block)
3434
block = _deprecated_scope_block("create!", &block)
35-
@association.enable_scoping do
36-
scoping { @association.create!(attributes, &block) }
35+
@association.scoping(self) do
36+
@association.create!(attributes, &block)
3737
end
3838
end
3939

activerecord/lib/active_record/associations/association.rb

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def initialize(owner, reflection)
4343
reflection.check_validity!
4444

4545
@owner, @reflection = owner, reflection
46-
@enable_scoping = false
46+
@_scope = nil
4747

4848
reset
4949
reset_scope
@@ -96,7 +96,7 @@ def target=(target)
9696
end
9797

9898
def scope
99-
target_scope.merge!(association_scope)
99+
@_scope&.spawn || target_scope.merge!(association_scope)
100100
end
101101

102102
def reset_scope
@@ -196,11 +196,11 @@ def create!(attributes = {}, &block)
196196
_create_record(attributes, true, &block)
197197
end
198198

199-
def enable_scoping
200-
@enable_scoping = true
201-
yield
199+
def scoping(relation, &block)
200+
@_scope = relation
201+
relation.scoping(&block)
202202
ensure
203-
@enable_scoping = false
203+
@_scope = nil
204204
end
205205

206206
private
@@ -233,11 +233,7 @@ def association_scope
233233
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
234234
# through association's scope)
235235
def target_scope
236-
AssociationRelation.create(klass, self).merge!(scope_for_association)
237-
end
238-
239-
def scope_for_association
240-
@enable_scoping ? klass.all : klass.scope_for_association
236+
AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
241237
end
242238

243239
def scope_for_create

activerecord/test/cases/associations/has_many_associations_test.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,15 @@ def test_build_and_create_from_association_should_respect_unscope_over_default_s
254254

255255
bulb = car.bulbs.unscope(where: :name).create!
256256
assert_nil bulb.name
257+
258+
bulb = car.awesome_bulbs.unscope(where: :frickinawesome).build
259+
assert_equal false, bulb.frickinawesome
260+
261+
bulb = car.awesome_bulbs.unscope(where: :frickinawesome).create
262+
assert_equal false, bulb.frickinawesome
263+
264+
bulb = car.awesome_bulbs.unscope(where: :frickinawesome).create!
265+
assert_equal false, bulb.frickinawesome
257266
end
258267

259268
def test_build_from_association_should_respect_scope

activerecord/test/cases/associations/has_many_through_associations_test.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,8 +688,10 @@ def test_associate_with_create
688688

689689
def test_through_record_is_built_when_created_with_where
690690
assert_difference("posts(:thinking).readers.count", 1) do
691-
posts(:thinking).people.where(first_name: "Jeb").create
691+
posts(:thinking).people.where(readers: { skimmer: true }).create(first_name: "Jeb")
692692
end
693+
reader = posts(:thinking).readers.last
694+
assert_equal true, reader.skimmer
693695
end
694696

695697
def test_associate_with_create_and_no_options

0 commit comments

Comments
 (0)