diff options
Diffstat (limited to 'railties/lib/rails/application')
-rw-r--r-- | railties/lib/rails/application/configuration.rb | 105 | ||||
-rw-r--r-- | railties/lib/rails/application/default_middleware_stack.rb | 2 | ||||
-rw-r--r-- | railties/lib/rails/application/dummy_erb_compiler.rb | 19 | ||||
-rw-r--r-- | railties/lib/rails/application/finisher.rb | 13 | ||||
-rw-r--r-- | railties/lib/rails/application/routes_reloader.rb | 22 |
5 files changed, 119 insertions, 42 deletions
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index bba573499d..b79dbdbc6f 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require "ipaddr" require "active_support/core_ext/kernel/reporting" require "active_support/file_update_checker" require "rails/engine/configuration" @@ -11,15 +12,16 @@ module Rails attr_accessor :allow_concurrency, :asset_host, :autoflush_log, :cache_classes, :cache_store, :consider_all_requests_local, :console, :eager_load, :exceptions_app, :file_watcher, :filter_parameters, - :force_ssl, :helpers_paths, :logger, :log_formatter, :log_tags, - :railties_order, :relative_url_root, :secret_key_base, :secret_token, + :force_ssl, :helpers_paths, :hosts, :logger, :log_formatter, :log_tags, + :railties_order, :relative_url_root, :secret_key_base, :ssl_options, :public_file_server, :session_options, :time_zone, :reload_classes_only_on_change, :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 + :content_security_policy_nonce_generator, :require_master_key, :credentials, + :disable_sandbox - attr_reader :encoding, :api_only, :loaded_config_version + attr_reader :encoding, :api_only, :loaded_config_version, :autoloader def initialize(*) super @@ -29,6 +31,7 @@ module Rails @filter_parameters = [] @filter_redirect = [] @helpers_paths = [] + @hosts = Array(([IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0"), ".localhost"] if Rails.env.development?)) @public_file_server = ActiveSupport::OrderedOptions.new @public_file_server.enabled = true @public_file_server.index_name = "index" @@ -48,7 +51,6 @@ module Rails @autoflush_log = true @log_formatter = ActiveSupport::Logger::SimpleFormatter.new @eager_load = nil - @secret_token = nil @secret_key_base = nil @api_only = false @debug_exception_response_format = nil @@ -60,6 +62,11 @@ module Rails @content_security_policy_nonce_generator = nil @require_master_key = false @loaded_config_version = nil + @credentials = ActiveSupport::OrderedOptions.new + @credentials.content_path = default_credentials_content_path + @credentials.key_path = default_credentials_key_path + @autoloader = :classic + @disable_sandbox = false end def load_defaults(target_version) @@ -92,10 +99,6 @@ module Rails if respond_to?(:active_record) active_record.cache_versioning = true - # Remove the temporary load hook from SQLite3Adapter when this is removed - ActiveSupport.on_load(:active_record_sqlite3adapter) do - ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true - end end if respond_to?(:action_dispatch) @@ -117,9 +120,28 @@ 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 + + if respond_to?(:action_dispatch) + action_dispatch.use_cookies_with_metadata = true + end + + if respond_to?(:action_mailer) + action_mailer.delivery_job = "ActionMailer::MailDeliveryJob" + end + + if respond_to?(:active_job) + active_job.return_false_on_aborted_enqueue = true + end + + if respond_to?(:active_storage) + active_storage.queues.analysis = :active_storage_analysis + active_storage.queues.purge = :active_storage_purge + end else raise "Unknown version #{target_version.to_s.inspect}" end @@ -146,9 +168,7 @@ module Rails @debug_exception_response_format || :default end - def debug_exception_response_format=(value) - @debug_exception_response_format = value - end + attr_writer :debug_exception_response_format def paths @paths ||= begin @@ -166,16 +186,24 @@ module Rails end end - # Loads the database YAML without evaluating ERB. People seem to - # write ERB that makes the database configuration depend on - # Rails configuration. But we want Rails configuration (specifically - # `rake` and `rails` tasks) to be generated based on information in - # the database yaml, so we need a method that loads the database - # yaml *without* the context of the Rails application. + # Load the database YAML without evaluating ERB. This allows us to + # create the rake tasks for multiple databases without filling in the + # configuration values or loading the environment. Do not use this + # method. + # + # This uses a DummyERB custom compiler so YAML can ignore the ERB + # tags and load the database.yml for the rake tasks. def load_database_yaml # :nodoc: - path = paths["config/database"].existent.first - return {} unless path - YAML.load_file(path.to_s) + if path = paths["config/database"].existent.first + require "rails/application/dummy_erb_compiler" + + yaml = Pathname.new(path) + erb = DummyERB.new(yaml.read) + + YAML.load(erb.result) + else + {} + end end # Loads and returns the entire raw configuration of database from @@ -209,7 +237,7 @@ module Rails "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \ "Error: #{e.message}" rescue => e - raise e, "Cannot load `Rails.application.database_configuration`:\n#{e.message}", e.backtrace + raise e, "Cannot load database configuration:\n#{e.message}", e.backtrace end def colorize_logging @@ -264,6 +292,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 @@ -283,6 +323,27 @@ module Rails true end end + + private + def default_credentials_content_path + if credentials_available_for_current_env? + root.join("config", "credentials", "#{Rails.env}.yml.enc") + else + root.join("config", "credentials.yml.enc") + end + end + + def default_credentials_key_path + if credentials_available_for_current_env? + root.join("config", "credentials", "#{Rails.env}.key") + else + root.join("config", "master.key") + end + end + + def credentials_available_for_current_env? + File.exist?(root.join("config", "credentials", "#{Rails.env}.yml.enc")) + end end end end diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb index 433a7ab41f..193cc59f3a 100644 --- a/railties/lib/rails/application/default_middleware_stack.rb +++ b/railties/lib/rails/application/default_middleware_stack.rb @@ -13,6 +13,8 @@ module Rails def build_stack ActionDispatch::MiddlewareStack.new do |middleware| + middleware.use ::ActionDispatch::HostAuthorization, config.hosts, config.action_dispatch.hosts_response_app + if config.force_ssl middleware.use ::ActionDispatch::SSL, config.ssl_options end diff --git a/railties/lib/rails/application/dummy_erb_compiler.rb b/railties/lib/rails/application/dummy_erb_compiler.rb new file mode 100644 index 0000000000..c4659123bb --- /dev/null +++ b/railties/lib/rails/application/dummy_erb_compiler.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# These classes are used to strip out the ERB configuration +# values so we can evaluate the database.yml without evaluating +# the ERB values. +class DummyERB < ERB # :nodoc: + def make_compiler(trim_mode) + DummyCompiler.new trim_mode + end +end + +class DummyCompiler < ERB::Compiler # :nodoc: + def compile_content(stag, out) + case stag + when "<%=" + out.push "_erbout << 'dummy_compiler'" + end + end +end diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index c4b188aeee..1cf44a480c 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(enable_reloading: !config.cache_classes) + end + end + initializer :add_builtin_route do |app| if Rails.env.development? app.routes.prepend do @@ -66,6 +73,10 @@ module Rails initializer :eager_load! do if config.eager_load ActiveSupport.run_load_hooks(:before_eager_load, self) + # Checks defined?(Zeitwerk) instead of zeitwerk_enabled? because we + # want to eager load any dependency managed by Zeitwerk regardless of + # the autoloading mode of the application. + Zeitwerk::Loader.eager_load_all if defined?(Zeitwerk) config.eager_load_namespaces.each(&:eager_load!) end end @@ -127,7 +138,7 @@ module Rails initializer :set_routes_reloader_hook do |app| reloader = routes_reloader reloader.eager_load = app.config.eager_load - reloader.execute_if_updated + reloader.execute reloaders << reloader app.reloader.to_run do # We configure #execute rather than #execute_if_updated because if diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb index 2ef09b4162..3ecb8e264e 100644 --- a/railties/lib/rails/application/routes_reloader.rb +++ b/railties/lib/rails/application/routes_reloader.rb @@ -7,7 +7,7 @@ module Rails class RoutesReloader attr_reader :route_sets, :paths attr_accessor :eager_load - delegate :updated?, to: :updater + delegate :execute_if_updated, :execute, :updated?, to: :updater def initialize @paths = [] @@ -19,31 +19,15 @@ module Rails clear! load_paths finalize! + route_sets.each(&:eager_load!) if eager_load ensure revert end - def execute - ret = updater.execute - route_sets.each(&:eager_load!) if eager_load - ret - end - - def execute_if_updated - if updated = updater.execute_if_updated - route_sets.each(&:eager_load!) if eager_load - end - updated - end - private def updater - @updater ||= begin - updater = ActiveSupport::FileUpdateChecker.new(paths) { reload! } - updater.execute - updater - end + @updater ||= ActiveSupport::FileUpdateChecker.new(paths) { reload! } end def clear! |