diff options
author | Xavier Noria <fxn@hashref.com> | 2019-04-28 00:22:13 +0200 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2019-04-28 13:48:26 +0200 |
commit | b6e17b6a4b67ccc9fac5fe16741c3db720f00959 (patch) | |
tree | b95094671664b01428f934f2faff9ae7f7989490 | |
parent | f9330abd986ba59a534f10836875ce9c1199aced (diff) | |
download | rails-b6e17b6a4b67ccc9fac5fe16741c3db720f00959.tar.gz rails-b6e17b6a4b67ccc9fac5fe16741c3db720f00959.tar.bz2 rails-b6e17b6a4b67ccc9fac5fe16741c3db720f00959.zip |
new config to opt-out from adding app directories to $LOAD_PATH
-rw-r--r-- | guides/source/configuring.md | 2 | ||||
-rw-r--r-- | railties/lib/rails/application/configuration.rb | 3 | ||||
-rw-r--r-- | railties/lib/rails/engine.rb | 13 | ||||
-rw-r--r-- | railties/test/application/configuration_test.rb | 28 |
4 files changed, 40 insertions, 6 deletions
diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 42da654fe7..b0173e5c97 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -64,6 +64,8 @@ These configuration methods are to be called on a `Rails::Railtie` object, such * `config.autoload_paths` accepts an array of paths from which Rails will autoload constants. Default is all directories under `app`. It is no longer recommended to adjust this. See [Autoloading and Reloading Constants](autoloading_and_reloading_constants.html#autoload-paths-and-eager-load-paths) +* `config.add_autoload_paths_to_load_path` says whether autoload paths have to be added to `$LOAD_PATH`. This flag is `true` by default, but it is recommended to be set to `false` in `:zeitwerk` mode early, in `config/application.rb`. Zeitwerk uses absolute paths internally, and applications running in `:zeitwerk` mode do not need `require_relative`, so models, controllers, jobs, etc. do not need to be in `$LOAD_PATH`. Setting this to `false` saves Ruby from checking these directories when resolving `require` calls with relative paths, and saves Bootsnap work and RAM, since it does not need to build an index for them. + * `config.cache_classes` controls whether or not application classes and modules should be reloaded on each request. Defaults to `false` in development mode, and `true` in test and production modes. * `config.beginning_of_week` sets the default beginning of week for the diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index ac86cc89be..0b758dd3dd 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -19,7 +19,7 @@ module Rails :beginning_of_week, :filter_redirect, :x, :enable_dependency_loading, :read_encrypted_secrets, :log_level, :content_security_policy_report_only, :content_security_policy_nonce_generator, :require_master_key, :credentials, - :disable_sandbox + :disable_sandbox, :add_autoload_paths_to_load_path attr_reader :encoding, :api_only, :loaded_config_version, :autoloader @@ -67,6 +67,7 @@ module Rails @credentials.key_path = default_credentials_key_path @autoloader = :classic @disable_sandbox = false + @add_autoload_paths_to_load_path = true end def load_defaults(target_version) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 06b4019fc7..d1b8c7803f 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -559,9 +559,8 @@ module Rails end end - # Add configured load paths to Ruby's load path, and remove duplicate entries. - initializer :set_load_path, before: :bootstrap_hook do - _all_load_paths.reverse_each do |path| + initializer :set_load_path, before: :bootstrap_hook do |app| + _all_load_paths(app.config.add_autoload_paths_to_load_path).reverse_each do |path| $LOAD_PATH.unshift(path) if File.directory?(path) end $LOAD_PATH.uniq! @@ -709,8 +708,12 @@ module Rails @_all_autoload_paths ||= (config.autoload_paths + config.eager_load_paths + config.autoload_once_paths).uniq end - def _all_load_paths - @_all_load_paths ||= (config.paths.load_paths + _all_autoload_paths).uniq + def _all_load_paths(add_autoload_paths_to_load_path) + @_all_load_paths ||= begin + load_paths = config.paths.load_paths + load_paths += _all_autoload_paths if add_autoload_paths_to_load_path + load_paths.uniq + end end def build_request(env) diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 62d9b1c813..7c613585e0 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -4,6 +4,7 @@ require "isolation/abstract_unit" require "rack/test" require "env_helpers" require "set" +require "active_support/core_ext/string/starts_ends_with" class ::MyMailInterceptor def self.delivering_email(email); email; end @@ -1704,6 +1705,33 @@ module ApplicationTests end end + test "autoload paths are added to $LOAD_PATH by default" do + app "development" + + # Action Mailer modifies AS::Dependencies.autoload_paths in-place. + autoload_paths = ActiveSupport::Dependencies.autoload_paths + autoload_paths_from_app_and_engines = autoload_paths.reject do |path| + path.ends_with?("mailers/previews") + end + assert_equal true, Rails.configuration.add_autoload_paths_to_load_path + assert_empty autoload_paths_from_app_and_engines - $LOAD_PATH + + # Precondition, ensure we are testing something next. + assert_not_empty Rails.configuration.paths.load_paths + assert_empty Rails.configuration.paths.load_paths - $LOAD_PATH + end + + test "autoload paths are not added to $LOAD_PATH if opted-out" do + add_to_config "config.add_autoload_paths_to_load_path = false" + app "development" + + assert_empty ActiveSupport::Dependencies.autoload_paths & $LOAD_PATH + + # Precondition, ensure we are testing something next. + assert_not_empty Rails.configuration.paths.load_paths + assert_empty Rails.configuration.paths.load_paths - $LOAD_PATH + end + test "autoloading during initialization gets deprecation message and clearing if config.cache_classes is false" do app_file "lib/c.rb", <<~EOS class C |