-
Notifications
You must be signed in to change notification settings - Fork 898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rails 7 #22873
Rails 7 #22873
Changes from all commits
3b74f5a
9b6ebb1
3263fdd
21bc1a9
b85a0c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -261,20 +261,73 @@ def scoped_name(name, scopes) | |
end | ||
|
||
module ArDescendantsWithLoader | ||
# Use caution if modifying the list of excluded caller_locations below. | ||
# These methods are called very early from rails during code load time, | ||
# before the models are even loaded, as documented below. | ||
# Ideally, a more resilient conditional can be used in the future. | ||
# | ||
# Called from __update_callbacks during model load time: | ||
# "xxx/gems/activesupport-7.0.8.4/lib/active_support/callbacks.rb:706:in `__update_callbacks'", | ||
# "xxx/gems/activesupport-7.0.8.4/lib/active_support/callbacks.rb:764:in `set_callback'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations.rb:172:in `validate'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations/with.rb:96:in `block in validates_with'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations/with.rb:85:in `each'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations/with.rb:85:in `validates_with'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations/format.rb:109:in `validates_format_of'", | ||
# "xxx/gems/ancestry-4.1.0/lib/ancestry/has_ancestry.rb:30:in `has_ancestry'", | ||
# "xxx/manageiq/app/models/vm_or_template.rb:15:in `<class:VmOrTemplate>'", | ||
# "xxx/manageiq/app/models/vm_or_template.rb:6:in `<main>'", | ||
def descendants | ||
if Vmdb::Application.instance.initialized? && !defined? @loaded_descendants | ||
if Vmdb::Application.instance.initialized? && !defined?(@loaded_descendants) && %w[__update_callbacks].exclude?(caller_locations(1..1).first.base_label) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the bot/cop complained about using caller_locations to build the full array so I accepted that suggestion even though I think it makes it a bit more convoluted. This method can be run many times, especially when models aren't yet loaded, so it should be as performant as possible. |
||
@loaded_descendants = true | ||
DescendantLoader.instance.load_subclasses(self) | ||
end | ||
|
||
super | ||
end | ||
|
||
# Rails 6.1 added an alias for subclasss to call direct_descendants in: | ||
# https://github.com/rails/rails/commit/8f8aa857e084b76b1120edaa9bb9ce03ba1e6a19 | ||
# We need to get in front of it, like we do for descendants. | ||
# Use caution if modifying the list of excluded caller_locations below. | ||
# These methods are called very early from rails during code load time, | ||
# before the models are even loaded, as documented below. | ||
# Ideally, a more resilient conditional can be used in the future. | ||
# | ||
# Called from reload_schema_from_cache from virtual column definitions from ar_region from many/all models: | ||
# "xxx/gems/activerecord-7.0.8.4/lib/active_record/model_schema.rb:609:in `reload_schema_from_cache'", | ||
# "xxx/gems/activerecord-7.0.8.4/lib/active_record/timestamp.rb:94:in `reload_schema_from_cache'", | ||
# "xxx/bundler/gems/activerecord-virtual_attributes-2c077434608f/lib/active_record/virtual_attributes.rb:60:in `virtual_attribute'", | ||
# "xxx/bundler/gems/activerecord-virtual_attributes-2c077434608f/lib/active_record/virtual_attributes.rb:55:in `virtual_column'", | ||
# "xxx/manageiq/lib/extensions/ar_region.rb:14:in `block in inherited'", | ||
# "xxx/manageiq/lib/extensions/ar_region.rb:13:in `class_eval'", | ||
# "xxx/manageiq/lib/extensions/ar_region.rb:13:in `inherited'", | ||
# "xxx/manageiq/app/models/vm_or_template.rb:6:in `<main>'", | ||
# | ||
# Called from subclasses call in descendant_loader after the above callstack: | ||
# "xxx/gems/activesupport-7.0.8.4/lib/active_support/descendants_tracker.rb:83:in `subclasses'", | ||
# "xxx/manageiq/lib/extensions/descendant_loader.rb:313:in `subclasses'", | ||
# "xxx/gems/activerecord-7.0.8.4/lib/active_record/model_schema.rb:609:in `reload_schema_from_cache'", | ||
# ... | ||
# | ||
# Called from descendants from descendant_loader via __update_callbacks: | ||
# "xxx/gems/activesupport-7.0.8.4/lib/active_support/descendants_tracker.rb:89:in `descendants'", | ||
# "xxx/manageiq/lib/extensions/descendant_loader.rb:296:in `descendants'", | ||
# "xxx/gems/activesupport-7.0.8.4/lib/active_support/callbacks.rb:706:in `__update_callbacks'", | ||
# "xxx/gems/activesupport-7.0.8.4/lib/active_support/callbacks.rb:764:in `set_callback'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations.rb:172:in `validate'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations/with.rb:96:in `block in validates_with'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations/with.rb:85:in `each'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations/with.rb:85:in `validates_with'", | ||
# "xxx/gems/activemodel-7.0.8.4/lib/active_model/validations/format.rb:109:in `validates_format_of'", | ||
# "xxx/gems/ancestry-4.1.0/lib/ancestry/has_ancestry.rb:30:in `has_ancestry'", | ||
# "xxx/manageiq/app/models/vm_or_template.rb:15:in `<class:VmOrTemplate>'", | ||
# "xxx/manageiq/app/models/vm_or_template.rb:6:in `<main>'", | ||
# | ||
# Called from subclasses from above callstack: | ||
# "xxx/gems/activesupport-7.0.8.4/lib/active_support/descendants_tracker.rb:83:in `subclasses'", | ||
# "xxx/manageiq/lib/extensions/descendant_loader.rb:313:in `subclasses'", | ||
# "xxx/gems/activesupport-7.0.8.4/lib/active_support/descendants_tracker.rb:89:in `descendants'", | ||
# ... | ||
def subclasses | ||
if Vmdb::Application.instance.initialized? && !defined? @loaded_descendants | ||
if Vmdb::Application.instance.initialized? && !defined?(@loaded_descendants) && %w[descendants reload_schema_from_cache subclasses].exclude?(caller_locations(1..1).first.base_label) | ||
@loaded_descendants = true | ||
DescendantLoader.instance.load_subclasses(self) | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,8 +45,11 @@ | |
FactoryBot.create_list(:vm, 2, :ext_management_system => ems) | ||
emses = ExtManagementSystem.all.load | ||
vms = Vm.where(:ems_id => emses.select(:id)) | ||
expect { preload(emses, :vms, vms) }.to make_database_queries(:count => 1) | ||
|
||
# TODO: With rails 7, the query count below increased by 1. | ||
# This PR says only the singular associations are preloaded in rails 7: | ||
# https://github.com/rails/rails/pull/42654 | ||
expect { preload(emses, :vms, vms) }.to make_database_queries(:count => 2) | ||
expect { expect(emses.first.vms.size).to eq(2) }.not_to make_database_queries | ||
Comment on lines
+52
to
53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm content with this answer. The most important part of this test is the second line: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, as I was looking at these tests, I was thinking some were not really the test and it's a test smell that we have several failures with rails 7 we needed to fix across the tests. Perhaps, we should have 1 failing test that we need to either mark pending, commented out with a TODO, etc. and remove the other assertions with comments that fail if they're testing the same things. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now, I just fixed the comments and made them todos |
||
end | ||
|
||
|
@@ -55,45 +58,73 @@ | |
vms = Vm.where(:ems_id => ems.id) | ||
vms2 = vms.order(:id).to_a # preloaded vms to be used in tests | ||
|
||
# there is a query for every ems | ||
expect { preload(ems, :vms, vms) }.to make_database_queries(:count => 1) | ||
# TODO: With rails 7, the query count below increased by 1. | ||
# This PR says only the singular associations are preloaded in rails 7: | ||
# https://github.com/rails/rails/pull/42654 | ||
expect { preload(ems, :vms, vms) }.to make_database_queries(:count => 2) | ||
|
||
expect { preload(ems, :vms, vms) }.not_to make_database_queries | ||
expect { expect(ems.vms).to match_array(vms2) }.not_to make_database_queries | ||
# vms does not get loaded, so it is not preloaded | ||
expect { expect(vms.first.ext_management_system).to eq(ems) }.to make_database_queries(:count => 2) | ||
|
||
# TODO: With rails 7, the query count below decreased by 1. | ||
expect { expect(vms.first.ext_management_system).to eq(ems) }.to make_database_queries(:count => 1) | ||
end | ||
|
||
it "preloads with a loaded relation (records is a relation)" do | ||
ems | ||
emses = ExtManagementSystem.all.load | ||
vms = Vm.where(:ems_id => emses.select(:id)).load | ||
expect { preload(emses, :vms, vms) }.not_to make_database_queries | ||
|
||
# TODO: With rails 7, the query count below increased by 1. | ||
# This PR says only the singular associations are preloaded in rails 7: | ||
# https://github.com/rails/rails/pull/42654 | ||
expect { preload(emses, :vms, vms) }.to make_database_queries(:count => 1) | ||
|
||
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 | ||
|
||
# TODO: With rails 7, the query count below increased by 1. | ||
expect { expect(vms.first.ext_management_system).to eq(ems) }.to make_database_queries(:count => 1) | ||
end | ||
|
||
it "preloads singular association with a loaded relation (records is a relation)" do | ||
emses = ExtManagementSystem.select(:id).where(:id => ems.id).load | ||
vms = Vm.where(:ems_id => emses.select(:id)).load | ||
preload(vms, :ext_management_system, emses) | ||
|
||
expect { preload(vms, :ext_management_system, emses) }.not_to make_database_queries | ||
expect { expect(vms.size).to eq(2) }.not_to make_database_queries | ||
expect { expect(vms.first.ext_management_system).to eq(emses.first) }.not_to make_database_queries | ||
end | ||
|
||
it "preloads with an array (records is a relation)" do | ||
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) }.to make_database_queries(:count => 1) | ||
|
||
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 | ||
|
||
# TODO: With rails 7, the query count below increased by 1. | ||
# This PR says only the singular associations are preloaded in rails 7: | ||
# https://github.com/rails/rails/pull/42654 | ||
expect { expect(vms.first.ext_management_system).to eq(ems) }.to make_database_queries(:count => 1) | ||
end | ||
|
||
it "preloads with an array (records is an array)" do | ||
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) }.to make_database_queries(:count => 1) | ||
|
||
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 | ||
|
||
# TODO: With rails 7, the query count below increased by 1. | ||
# This PR says only the singular associations are preloaded in rails 7: | ||
# https://github.com/rails/rails/pull/42654 | ||
expect { expect(vms.first.ext_management_system).to eq(ems) }.to make_database_queries(:count => 1) | ||
end | ||
|
||
it "preloads a through with a loaded scope" do | ||
|
@@ -109,8 +140,8 @@ | |
expect { expect(nodes.first.container_images).to eq([image]) }.to make_database_queries(:count => 1) | ||
end | ||
|
||
def preload(*args) | ||
MiqPreloader.preload(*args) | ||
def preload(*args, **kwargs) | ||
MiqPreloader.preload(*args, **kwargs) | ||
end | ||
end | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pushed this change to set minimum to ensure latest CVE coverage