aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib')
-rw-r--r--railties/lib/rails.rb20
-rw-r--r--railties/lib/rails/application.rb38
-rw-r--r--railties/lib/rails/application/configuration.rb17
-rw-r--r--railties/lib/rails/application/finisher.rb8
-rw-r--r--railties/lib/rails/command/behavior.rb5
-rw-r--r--railties/lib/rails/engine.rb26
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile.tt2
7 files changed, 104 insertions, 12 deletions
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb
index 092105d502..bca2cf34e1 100644
--- a/railties/lib/rails.rb
+++ b/railties/lib/rails.rb
@@ -110,5 +110,25 @@ module Rails
def public_path
application && Pathname.new(application.paths["public"].first)
end
+
+ def autoloader
+ if configuration.autoloader == :zeitwerk
+ @autoloader ||= Zeitwerk::Loader.new
+ end
+ end
+
+ def once_autoloader
+ if configuration.autoloader == :zeitwerk
+ @once_autoloader ||= Zeitwerk::Loader.new
+ end
+ end
+
+ def autoloaders
+ if configuration.autoloader == :zeitwerk
+ [autoloader, once_autoloader]
+ else
+ []
+ end
+ end
end
end
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 5a924ab8e6..d0417f8a49 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -7,6 +7,7 @@ require "active_support/key_generator"
require "active_support/message_verifier"
require "active_support/encrypted_configuration"
require "active_support/deprecation"
+require "active_support/hash_with_indifferent_access"
require "rails/engine"
require "rails/secrets"
@@ -230,8 +231,8 @@ module Rails
config = YAML.load(ERB.new(yaml.read).result) || {}
config = (config["shared"] || {}).merge(config[env] || {})
- ActiveSupport::OrderedOptions.new.tap do |config_as_ordered_options|
- config_as_ordered_options.update(config.deep_symbolize_keys)
+ ActiveSupport::OrderedOptions.new.tap do |options|
+ options.update(NonSymbolAccessDeprecatedHash.new(config))
end
else
raise "Could not load configuration. No such file - #{yaml}"
@@ -590,5 +591,38 @@ module Rails
def build_middleware
config.app_middleware + super
end
+
+ class NonSymbolAccessDeprecatedHash < HashWithIndifferentAccess # :nodoc:
+ def initialize(value = nil)
+ if value.is_a?(Hash)
+ value.each_pair { |k, v| self[k] = v }
+ else
+ super
+ end
+ end
+
+ def []=(key, value)
+ if value.is_a?(Hash)
+ value = self.class.new(value)
+ end
+ super(key.to_sym, value)
+ end
+
+ private
+
+ def convert_key(key)
+ unless key.kind_of?(Symbol)
+ ActiveSupport::Deprecation.warn(<<~MESSAGE.squish)
+ Accessing hashes returned from config_for by non-symbol keys
+ is deprecated and will be removed in Rails 6.1.
+ Use symbols for access instead.
+ MESSAGE
+
+ key = key.to_sym
+ end
+
+ key
+ end
+ end
end
end
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index b7838f7e32..af3ec36064 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -20,7 +20,7 @@ module Rails
:read_encrypted_secrets, :log_level, :content_security_policy_report_only,
:content_security_policy_nonce_generator, :require_master_key, :credentials
- attr_reader :encoding, :api_only, :loaded_config_version
+ attr_reader :encoding, :api_only, :loaded_config_version, :autoloader
def initialize(*)
super
@@ -64,6 +64,7 @@ module Rails
@credentials = ActiveSupport::OrderedOptions.new
@credentials.content_path = default_credentials_content_path
@credentials.key_path = default_credentials_key_path
+ @autoloader = :classic
end
def load_defaults(target_version)
@@ -117,6 +118,8 @@ module Rails
when "6.0"
load_defaults "5.2"
+ self.autoloader = :zeitwerk if RUBY_ENGINE == "ruby"
+
if respond_to?(:action_view)
action_view.default_enforce_utf8 = false
end
@@ -267,6 +270,18 @@ module Rails
end
end
+ def autoloader=(autoloader)
+ case autoloader
+ when :classic
+ @autoloader = autoloader
+ when :zeitwerk
+ require "zeitwerk"
+ @autoloader = autoloader
+ else
+ raise ArgumentError, "config.autoloader may be :classic or :zeitwerk, got #{autoloader.inspect} instead"
+ end
+ end
+
class Custom #:nodoc:
def initialize
@configurations = Hash.new
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index 04aaf6dd9a..39e8ef6631 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -21,6 +21,13 @@ module Rails
end
end
+ initializer :let_zeitwerk_take_over do
+ if config.autoloader == :zeitwerk
+ require "active_support/dependencies/zeitwerk_integration"
+ ActiveSupport::Dependencies::ZeitwerkIntegration.take_over
+ end
+ end
+
initializer :add_builtin_route do |app|
if Rails.env.development?
app.routes.prepend do
@@ -66,6 +73,7 @@ module Rails
initializer :eager_load! do
if config.eager_load
ActiveSupport.run_load_hooks(:before_eager_load, self)
+ Zeitwerk::Loader.eager_load_all if defined?(Zeitwerk)
config.eager_load_namespaces.each(&:eager_load!)
end
end
diff --git a/railties/lib/rails/command/behavior.rb b/railties/lib/rails/command/behavior.rb
index 7f32b04cf1..7fb2a99e67 100644
--- a/railties/lib/rails/command/behavior.rb
+++ b/railties/lib/rails/command/behavior.rb
@@ -71,8 +71,9 @@ module Rails
paths = []
namespaces.each do |namespace|
pieces = namespace.split(":")
- paths << pieces.dup.push(pieces.last).join("/")
- paths << pieces.join("/")
+ path = pieces.join("/")
+ paths << "#{path}/#{pieces.last}"
+ paths << path
end
paths.uniq!
paths
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index d6c329b581..2485158a7b 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -472,12 +472,10 @@ module Rails
# Eager load the application by loading all ruby
# files inside eager_load paths.
def eager_load!
- config.eager_load_paths.each do |load_path|
- # Starts after load_path plus a slash, ends before ".rb".
- relname_range = (load_path.to_s.length + 1)...-3
- Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
- require_dependency file[relname_range]
- end
+ if Rails.autoloader
+ eager_load_with_zeitwerk!
+ else
+ eager_load_with_dependencies!
end
end
@@ -653,6 +651,22 @@ module Rails
private
+ def eager_load_with_zeitwerk!
+ (config.eager_load_paths - Zeitwerk::Loader.all_dirs).each do |path|
+ Dir.glob("#{path}/**/*.rb").sort.each { |file| require file }
+ end
+ end
+
+ def eager_load_with_dependencies!
+ config.eager_load_paths.each do |load_path|
+ # Starts after load_path plus a slash, ends before ".rb".
+ relname_range = (load_path.to_s.length + 1)...-3
+ Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
+ require_dependency file[relname_range]
+ end
+ end
+ end
+
def load_config_initializer(initializer) # :doc:
ActiveSupport::Notifications.instrument("load_config_initializer.railties", initializer: initializer) do
load(initializer)
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt
index d39b5d311f..783254b54d 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt
@@ -28,7 +28,7 @@ ruby <%= "'#{RUBY_VERSION}'" -%>
<% if depend_on_bootsnap? -%>
# Reduces boot times through caching; required in config/boot.rb
-gem 'bootsnap', '>= 1.1.0', require: false
+gem 'bootsnap', '>= 1.4.0', require: false
<%- end -%>
<%- if options.api? -%>