From 118c2bf5e093c832b40f4a4d815faf3cfa9d2b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Mon, 15 Apr 2024 20:14:22 +0200 Subject: [PATCH] Move custom ActiveStorage service to $LOAD_PATH We moved this file to `app/lib/` in commit cb477149c so it would be in the autoload_paths. However, this class is loaded by ActiveStorage, with the following method: ``` def resolve(class_name) require "active_storage/service/#{class_name.to_s.underscore}_service" ActiveStorage::Service.const_get(:"#{class_name.camelize}Service") rescue LoadError raise "Missing service adapter for #{class_name.inspect}" end `` So this file needs to be in the $LOAD_PATH, or else ActiveStorage won't be able to load it when we disable the `add_autoload_paths_to_load_path` option, which is the default in Rails 7.1 [1]. Moving it to the `lib` folder solves the issue; as mentioned in the guide to upgrade to Rails 7.1 [2]: > The lib directory is not affected by this flag, it is added to > $LOAD_PATH always. However, we were also referencing this class in the `Tenant` model, meaning we needed to autoload it as well somehow. So, instead of directly referencing this class, we're using `respond_to?` in the Tenant model. We're changing the test so it fails when the code calls `is_a?(ActiveStorage::Service::TenantDiskService)`. We need to change the active storage configurations in the test because, otherwise, the moment `ActiveStorage::Blob` is loaded, the `TenantDiskService` class is also loaded, meaning the test will pass when using `is_a?`. Note that, since this class isn't in the autoload paths anymore, we need to add a `require` in the tests. We could add an initializer to require it; we're not doing it in order to be consistent with what ActiveStorage does: it only loads the service that's going to be used in the current Rails environment. If somebody changed their production environment in order to use (for example), S3, and we added an initializer to require the TenantDiskService, we would still load the TenantDiskService even if it isn't going to be used. [1] https://guides.rubyonrails.org/v7.1/configuring.html#config-add-autoload-paths-to-load-path [2] https://guides.rubyonrails.org/v7.1/upgrading_ruby_on_rails.html#autoloaded-paths-are-no-longer-in-$load-path --- app/models/tenant.rb | 2 +- .../active_storage/service/tenant_disk_service.rb | 0 .../active_storage/service/tenant_disk_service_spec.rb | 1 + spec/models/tenant_spec.rb | 10 +++++++--- 4 files changed, 9 insertions(+), 4 deletions(-) rename {app/lib => lib}/active_storage/service/tenant_disk_service.rb (100%) diff --git a/app/models/tenant.rb b/app/models/tenant.rb index 3ca57558a..e39d3cd9c 100644 --- a/app/models/tenant.rb +++ b/app/models/tenant.rb @@ -184,7 +184,7 @@ class Tenant < ApplicationRecord def rename_storage service = ActiveStorage::Blob.service - return unless service.is_a?(ActiveStorage::Service::TenantDiskService) + return unless service.respond_to?(:tenant_root_for) old_storage = service.tenant_root_for(schema_before_last_save) diff --git a/app/lib/active_storage/service/tenant_disk_service.rb b/lib/active_storage/service/tenant_disk_service.rb similarity index 100% rename from app/lib/active_storage/service/tenant_disk_service.rb rename to lib/active_storage/service/tenant_disk_service.rb diff --git a/spec/lib/active_storage/service/tenant_disk_service_spec.rb b/spec/lib/active_storage/service/tenant_disk_service_spec.rb index 74e94537a..28ad722d1 100644 --- a/spec/lib/active_storage/service/tenant_disk_service_spec.rb +++ b/spec/lib/active_storage/service/tenant_disk_service_spec.rb @@ -1,4 +1,5 @@ require "rails_helper" +require "active_storage/service/tenant_disk_service" describe ActiveStorage::Service::TenantDiskService do describe "#tenant_root_for" do diff --git a/spec/models/tenant_spec.rb b/spec/models/tenant_spec.rb index ca6be56be..e7244c226 100644 --- a/spec/models/tenant_spec.rb +++ b/spec/models/tenant_spec.rb @@ -424,9 +424,13 @@ describe Tenant do FileUtils.rm_rf(File.join(ActiveStorage::Blob.service.root, "tenants", "notypo")) end - it "does nothing when the active storage blob service is not a TenantDiskService" do - disk_service = ActiveStorage::Service::DiskService.new(root: ActiveStorage::Blob.service.root) - allow(ActiveStorage::Blob).to receive(:service).and_return(disk_service) + it "does nothing when the active storage blob service cannot manage tenants" do + allow(Rails.configuration.active_storage).to receive(:service_configurations) do + ActiveSupport::ConfigurationFile.parse(Rails.root.join("config/storage.yml")).tap do |config| + config[Rails.configuration.active_storage.service.to_s]["service"] = "Disk" + end + end + tenant = create(:tenant, schema: "typo") expect(File).not_to receive(:rename)