diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 2a4fa932b5..11dbae367d 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -53,19 +53,33 @@ module ActiveSupport # :nodoc: # main autoloader. Used to clear state. mattr_accessor :_autoloaded_tracked_classes, default: Set.new + # Private method that reloads constants autoloaded by the main autoloader. + # + # Rails.application.reloader.reload! is the public interface for application + # reload. That involves more things, like deleting unloaded classes from the + # internal state of the descendants tracker, or reloading routes. + def self.clear + unload_interlock do + _autoloaded_tracked_classes.clear + Rails.autoloaders.main.reload + rescue Zeitwerk::ReloadingDisabledError + raise "reloading is disabled because config.cache_classes is true" + end + end + + # Private method used by require_dependency. + def self.search_for_file(relpath) + relpath += ".rb" unless relpath.end_with?(".rb") + autoload_paths.each do |autoload_path| + abspath = File.join(autoload_path, relpath) + return abspath if File.file?(abspath) + end + nil + end + + # Private method that helps configuring the autoloaders. def self.eager_load?(path) _eager_load_paths.member?(path) end - - # Search for a file in autoload_paths matching the provided suffix. - def self.search_for_file(path_suffix) - path_suffix += ".rb" unless path_suffix.end_with?(".rb") - - autoload_paths.each do |root| - path = File.join(root, path_suffix) - return path if File.file? path - end - nil # Gee, I sure wish we had first_match ;-) - end end end diff --git a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb b/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb index 81d1e5c4de..68ebcd69ae 100644 --- a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb +++ b/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb @@ -6,17 +6,6 @@ require "zeitwerk" module ActiveSupport module Dependencies module ZeitwerkIntegration # :nodoc: all - module Decorations - def clear - Dependencies.unload_interlock do - _autoloaded_tracked_classes.clear - Rails.autoloaders.main.reload - rescue Zeitwerk::ReloadingDisabledError - raise "reloading is disabled because config.cache_classes is true" - end - end - end - module Inflector # Concurrent::Map is not needed. This is a private class, and overrides # must be defined while the application boots. @@ -30,10 +19,6 @@ module ActiveSupport @overrides.merge!(overrides) end end - - def self.take_over - Dependencies.singleton_class.prepend(Decorations) - end end end end diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index e15caa02de..7c8a7a1302 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true +require "zeitwerk" require "active_support/core_ext/string/inflections" require "active_support/core_ext/array/conversions" require "active_support/descendants_tracker" require "active_support/dependencies" -require "zeitwerk" module Rails class Application @@ -44,11 +44,6 @@ module Rails autoloader.setup end - initializer :let_zeitwerk_take_over do - require "active_support/dependencies/zeitwerk_integration" - ActiveSupport::Dependencies::ZeitwerkIntegration.take_over - end - # Setup default session store if not already set in config/application.rb initializer :setup_default_session_store, before: :build_middleware_stack do |app| unless app.config.session_store? @@ -179,6 +174,7 @@ module Rails # added in the hook are taken into account. initializer :set_clear_dependencies_hook, group: :all do |app| callback = lambda do + # Order matters. ActiveSupport::DescendantsTracker.clear( only: ActiveSupport::Dependencies._autoloaded_tracked_classes ) diff --git a/railties/lib/rails/autoloaders.rb b/railties/lib/rails/autoloaders.rb index c2e5e64aef..27d1feb031 100644 --- a/railties/lib/rails/autoloaders.rb +++ b/railties/lib/rails/autoloaders.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require "active_support/dependencies/zeitwerk_integration" require "zeitwerk" +require "active_support/dependencies/zeitwerk_integration" module Rails module Autoloaders # :nodoc: diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb index f1febd2653..ab771518b4 100644 --- a/railties/test/application/rake/multi_dbs_test.rb +++ b/railties/test/application/rake/multi_dbs_test.rb @@ -440,6 +440,7 @@ module ApplicationTests end test "db:migrate set back connection to its original state" do + require "#{app_path}/config/environment" Dir.chdir(app_path) do dummy_task = <<~RUBY task foo: :environment do @@ -457,6 +458,7 @@ module ApplicationTests end test "db:migrate:name sets the connection back to its original state" do + require "#{app_path}/config/environment" Dir.chdir(app_path) do dummy_task = <<~RUBY task foo: :environment do @@ -1067,6 +1069,7 @@ module ApplicationTests end test "when database_tasks is false, then do not run the database tasks on that db" do + require "#{app_path}/config/environment" app_file "config/database.yml", <<-YAML development: primary: diff --git a/railties/test/application/zeitwerk_integration_test.rb b/railties/test/application/zeitwerk_integration_test.rb index 19fa5fd88e..060fd7750c 100644 --- a/railties/test/application/zeitwerk_integration_test.rb +++ b/railties/test/application/zeitwerk_integration_test.rb @@ -23,14 +23,9 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase ActiveSupport::Dependencies end - def decorated? - deps.singleton_class < deps::ZeitwerkIntegration::Decorations - end - - test "ActiveSupport::Dependencies is decorated" do + test "The integration is minimally looking good" do boot - assert decorated? assert Rails.autoloaders.zeitwerk_enabled? assert_instance_of Zeitwerk::Loader, Rails.autoloaders.main assert_instance_of Zeitwerk::Loader, Rails.autoloaders.once