diff --git a/lib/extensions/ar_preloader.rb b/lib/extensions/ar_preloader.rb new file mode 100644 index 000000000000..d1b23f44f82b --- /dev/null +++ b/lib/extensions/ar_preloader.rb @@ -0,0 +1,18 @@ +module ActiveRecordPreloadScopes + # based upon active record 6.1 + def records_for(ids) + # use our logic if passing in [ActiveRecord::Base] or passing in a loaded Relation/scope + unless (preload_scope.kind_of?(Array) && preload_scope.first.kind_of?(ActiveRecord::Base)) || + preload_scope.try(:loaded?) + return super + end + + preload_scope.each do |record| + owner = owners_by_key[convert_key(record[association_key_name])].first + association = owner.association(reflection.name) + association.set_inverse_instance(record) + end + end +end + +ActiveRecord::Associations::Preloader::Association.prepend(ActiveRecordPreloadScopes) diff --git a/spec/lib/miq_preloader_spec.rb b/spec/lib/miq_preloader_spec.rb index 020e659e8dde..c66db0ad8c51 100644 --- a/spec/lib/miq_preloader_spec.rb +++ b/spec/lib/miq_preloader_spec.rb @@ -36,6 +36,45 @@ expect { preload(emses, :vms, vms) }.to make_database_queries(:count => 1) end + it "preloads with a loaded relation (records is a relation)" do + ems = FactoryBot.create(:ems_infra) + FactoryBot.create_list(:vm, 2, :ext_management_system => ems) + + emses = ExtManagementSystem.all.load + vms = Vm.where(:ems_id => emses.select(:id)).load + + expect { preload(emses, :vms, vms) }.not_to make_database_queries + expect { preload(emses, :vms, vms) }.not_to make_database_queries + expect { expect(emses.first.vms.size).to eq(2) }.not_to make_database_queries + expect { expect(vms.first.ext_management_system).to eq(ems) }.not_to make_database_queries + end + + it "preloads with an array (records is a relation)" do + ems = FactoryBot.create(:ems_infra) + FactoryBot.create_list(:vm, 2, :ext_management_system => ems) + + emses = ExtManagementSystem.all.load + vms = Vm.where(:ems_id => emses.select(:id)).to_a + + expect { preload(emses, :vms, vms) }.not_to make_database_queries + expect { preload(emses, :vms, vms) }.not_to make_database_queries + expect { expect(emses.first.vms.size).to eq(2) }.not_to make_database_queries + expect { expect(vms.first.ext_management_system).to eq(ems) }.not_to make_database_queries + end + + it "preloads with an array (records is an array)" do + ems = FactoryBot.create(:ems_infra) + FactoryBot.create_list(:vm, 2, :ext_management_system => ems) + + emses = ExtManagementSystem.all.load.to_a + vms = Vm.where(:ems_id => emses.map(&:id)).to_a + + expect { preload(emses, :vms, vms) }.not_to make_database_queries + expect { preload(emses, :vms, vms) }.not_to make_database_queries + expect { expect(emses.first.vms.size).to eq(2) }.not_to make_database_queries + expect { expect(vms.first.ext_management_system).to eq(ems) }.not_to make_database_queries + end + def preload(*args) MiqPreloader.preload(*args) end