Skip to content

Commit 2d988d0

Browse files
authored
Fix STI in available_records causing new instances of records to be loaded from database
Removes grouping by available_record class names in ActiveRecord::Associations::Preloader::Batch so that records of differing STI classes can be located.
1 parent 6d7fdba commit 2d988d0

File tree

5 files changed

+25
-3
lines changed

5 files changed

+25
-3
lines changed

activerecord/lib/active_record/associations/preloader/association.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ def associate_records_from_unscoped(unscoped_records)
205205
return if preload_scope && !preload_scope.empty_scope?
206206
return if reflection.collection?
207207

208-
unscoped_records.each do |record|
208+
unscoped_records.select { |r| r[association_key_name].present? }.each do |record|
209209
owners = owners_by_key[convert_key(record[association_key_name])]
210210
owners&.each_with_index do |owner, i|
211211
association = owner.association(reflection.name)

activerecord/lib/active_record/associations/preloader/batch.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ class Preloader
66
class Batch # :nodoc:
77
def initialize(preloaders, available_records:)
88
@preloaders = preloaders.reject(&:empty?)
9-
@available_records = available_records.flatten.group_by(&:class)
9+
@available_records = available_records.flatten
1010
end
1111

1212
def call
1313
branches = @preloaders.flat_map(&:branches)
1414
until branches.empty?
1515
loaders = branches.flat_map(&:runnable_loaders)
1616

17-
loaders.each { |loader| loader.associate_records_from_unscoped(@available_records[loader.klass]) }
17+
loaders.each { |loader| loader.associate_records_from_unscoped(@available_records) }
1818

1919
if loaders.any?
2020
future_tables = branches.flat_map do |branch|

activerecord/test/cases/associations_test.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,23 @@ def test_preload_with_available_records
804804
end
805805
end
806806

807+
def test_preload_with_available_records_sti
808+
book = Book.create!
809+
essay_special = EssaySpecial.create!
810+
book.essay = essay_special
811+
book.save!
812+
book.reload
813+
814+
assert_not_predicate book.association(:essay), :loaded?
815+
816+
assert_no_queries do
817+
ActiveRecord::Associations::Preloader.new(records: [book], associations: :essay, available_records: [[essay_special]]).call
818+
end
819+
820+
assert_predicate book.association(:essay), :loaded?
821+
assert_same essay_special, book.essay
822+
end
823+
807824
def test_preload_with_only_some_records_available
808825
bob_post = posts(:misc_by_bob)
809826
mary_post = posts(:misc_by_mary)

activerecord/test/models/book.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class Book < ActiveRecord::Base
99
has_many :subscriptions
1010
has_many :subscribers, through: :subscriptions
1111

12+
has_one :essay
13+
1214
enum status: [:proposed, :written, :published]
1315
enum last_read: { unread: 0, reading: 2, read: 3, forgotten: nil }
1416
enum nullable_status: [:single, :married]

activerecord/test/models/essay.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ class Essay < ActiveRecord::Base
66
belongs_to :category, primary_key: :name
77
has_one :owner, primary_key: :name
88
end
9+
10+
class EssaySpecial < Essay
11+
end

0 commit comments

Comments
 (0)