aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRafael Mendonça França <rafaelmfranca@gmail.com>2019-02-26 18:07:13 -0500
committerRafael Mendonça França <rafaelmfranca@gmail.com>2019-02-26 18:07:13 -0500
commit572dcdd7e858f126848bdf4f2be0f5cb0de7c026 (patch)
treeb0bad61734f2ded9782bf51cd701bffb1a6e56d9 /activerecord
parent196e22de5378cf684760f082c8131f728f4717c4 (diff)
downloadrails-572dcdd7e858f126848bdf4f2be0f5cb0de7c026.tar.gz
rails-572dcdd7e858f126848bdf4f2be0f5cb0de7c026.tar.bz2
rails-572dcdd7e858f126848bdf4f2be0f5cb0de7c026.zip
Fix preload with nested associations
When the middle association doesn't have any records and the inner association is not an empty scope the owner will be `nil` so we can't try to reset the inverse association.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/preloader/through_association.rb6
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb9
-rw-r--r--activerecord/test/models/author.rb2
3 files changed, 16 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb
index 25254e652a..32653956b2 100644
--- a/activerecord/lib/active_record/associations/preloader/through_association.rb
+++ b/activerecord/lib/active_record/associations/preloader/through_association.rb
@@ -14,6 +14,7 @@ module ActiveRecord
owners.each do |owner|
through_records = Array(owner.association(through_reflection.name).target)
+
if already_loaded
if source_type = reflection.options[:source_type]
through_records = through_records.select do |record|
@@ -23,17 +24,20 @@ module ActiveRecord
else
owner.association(through_reflection.name).reset if through_scope
end
+
result = through_records.flat_map do |record|
record.association(source_reflection.name).target
end
+
result.compact!
result.sort_by! { |rhs| preload_index[rhs] } if scope.order_values.any?
result.uniq! if scope.distinct_value
associate_records_to_owner(owner, result)
end
+
unless scope.empty_scope?
middle_records.each do |owner|
- owner.association(source_reflection.name).reset
+ owner.association(source_reflection.name).reset if owner
end
end
end
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 0ac56c6168..6f23a832ef 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -55,6 +55,15 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert_equal preloaded, Marshal.load(Marshal.dump(preloaded))
end
+ def test_preload_with_nested_association
+ posts = Post.preload(:author, :author_favorites).to_a
+
+ assert_no_queries do
+ posts.each(&:author)
+ posts.each(&:author_favorites)
+ end
+ end
+
def test_preload_sti_rhs_class
developers = Developer.includes(:firms).all.to_a
assert_no_queries do
diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb
index 8b5a2fa0c8..3eb8a3a0fa 100644
--- a/activerecord/test/models/author.rb
+++ b/activerecord/test/models/author.rb
@@ -217,6 +217,8 @@ class AuthorAddress < ActiveRecord::Base
end
class AuthorFavorite < ActiveRecord::Base
+ default_scope { order(id: :asc) }
+
belongs_to :author
belongs_to :favorite_author, class_name: "Author"
end