diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2019-02-26 18:07:13 -0500 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2019-02-26 18:07:13 -0500 |
commit | 572dcdd7e858f126848bdf4f2be0f5cb0de7c026 (patch) | |
tree | b0bad61734f2ded9782bf51cd701bffb1a6e56d9 | |
parent | 196e22de5378cf684760f082c8131f728f4717c4 (diff) | |
download | rails-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.
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 |