2017-08-14 13:08:09 -04:00
# frozen_string_literal: true
2019-04-14 05:37:50 -04:00
require " active_support/core_ext/string/inflections "
require " active_support/core_ext/array/conversions "
2010-01-23 10:07:20 -05:00
module Rails
class Application
module Finisher
include Initializable
2010-04-05 04:52:47 -04:00
initializer :add_generator_templates do
2010-10-06 11:18:59 -04:00
config . generators . templates . unshift ( * paths [ " lib/templates " ] . existent )
2010-04-05 04:52:47 -04:00
end
2010-06-22 17:17:20 -04:00
initializer :ensure_autoload_once_paths_as_subset do
extra = ActiveSupport :: Dependencies . autoload_once_paths -
ActiveSupport :: Dependencies . autoload_paths
2010-01-23 11:13:25 -05:00
unless extra . empty?
abort <<-end_error
2010-06-22 17:17:20 -04:00
autoload_once_paths must be a subset of the autoload_paths .
Extra items in autoload_once_paths : #{extra * ','}
2010-01-23 11:13:25 -05:00
end_error
end
end
2019-04-14 05:37:50 -04:00
# This will become an error if/when we remove classic mode. The plan is
# autoloaders won't be configured up to this point in the finisher, so
# constants just won't be found, raising regular NameError exceptions.
initializer :warn_if_autoloaded , before : :let_zeitwerk_take_over do
next if config . cache_classes
next if ActiveSupport :: Dependencies . autoloaded_constants . empty?
autoloaded = ActiveSupport :: Dependencies . autoloaded_constants
constants = " constant " . pluralize ( autoloaded . size )
enum = autoloaded . to_sentence
have = autoloaded . size == 1 ? " has " : " have "
these = autoloaded . size == 1 ? " This " : " These "
example = autoloaded . first
example_klass = example . constantize . class
2019-06-04 10:02:04 -04:00
if config . autoloader == :zeitwerk
ActiveSupport :: DescendantsTracker . clear
ActiveSupport :: Dependencies . clear
unload_message = " #{ these } autoloaded #{ constants } #{ have } been unloaded. "
else
unload_message = " `config.autoloader` is set to ` #{ config . autoloader } `. #{ these } autoloaded #{ constants } would have been unloaded if `config.autoloader` had been set to `:zeitwerk`. "
end
2019-04-14 05:37:50 -04:00
ActiveSupport :: Deprecation . warn ( << ~ WARNING )
Initialization autoloaded the #{constants} #{enum}.
Being able to do this is deprecated . Autoloading during initialization is going
to be an error condition in future versions of Rails .
Reloading does not reboot the application , and therefore code executed during
initialization does not run again . So , if you reload #{example}, for example,
the expected changes won ' t be reflected in that stale #{example_klass} object.
2019-06-04 10:02:04 -04:00
#{unload_message}
2019-04-14 05:37:50 -04:00
Please , check the " Autoloading and Reloading Constants " guide for solutions .
WARNING
end
2019-02-11 15:44:25 -05:00
initializer :let_zeitwerk_take_over do
if config . autoloader == :zeitwerk
require " active_support/dependencies/zeitwerk_integration "
2019-04-07 06:30:34 -04:00
ActiveSupport :: Dependencies :: ZeitwerkIntegration . take_over ( enable_reloading : ! config . cache_classes )
2019-02-11 15:44:25 -05:00
end
end
2010-01-27 11:39:35 -05:00
initializer :add_builtin_route do | app |
2010-01-23 10:07:20 -05:00
if Rails . env . development?
2016-06-18 04:46:44 -04:00
app . routes . prepend do
2016-08-06 13:15:47 -04:00
get " /rails/info/properties " = > " rails/info # properties " , internal : true
get " /rails/info/routes " = > " rails/info # routes " , internal : true
get " /rails/info " = > " rails/info # index " , internal : true
2016-06-18 04:46:44 -04:00
end
app . routes . append do
2016-08-06 13:15:47 -04:00
get " / " = > " rails/welcome # index " , internal : true
2010-09-17 15:27:48 -04:00
end
2010-01-23 10:07:20 -05:00
end
end
2016-07-17 10:08:54 -04:00
# 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?
2016-08-06 13:15:47 -04:00
app_name = app . class . name ? app . railtie_name . chomp ( " _application " ) : " "
2016-07-17 10:08:54 -04:00
app . config . session_store :cookie_store , key : " _ #{ app_name } _session "
end
end
2010-02-19 02:02:28 -05:00
initializer :build_middleware_stack do
2010-06-20 19:08:50 -04:00
build_middleware_stack
2010-02-19 02:02:28 -05:00
end
2011-04-25 08:56:58 -04:00
initializer :define_main_app_helper do | app |
app . routes . define_mounted_helper ( :main_app )
end
2016-02-21 20:25:52 -05:00
initializer :add_to_prepare_blocks do | app |
2011-12-12 09:18:19 -05:00
config . to_prepare_blocks . each do | block |
2016-02-21 20:25:52 -05:00
app . reloader . to_prepare ( & block )
2011-12-12 09:18:19 -05:00
end
end
# This needs to happen before eager load so it happens
2017-12-30 17:37:44 -05:00
# in exactly the same point regardless of config.eager_load
2016-02-21 20:25:52 -05:00
initializer :run_prepare_callbacks do | app |
app . reloader . prepare!
2011-12-12 09:18:19 -05:00
end
2010-05-15 17:48:56 -04:00
initializer :eager_load! do
2012-08-01 09:07:01 -04:00
if config . eager_load
2010-05-15 18:34:54 -04:00
ActiveSupport . run_load_hooks ( :before_eager_load , self )
2019-02-20 17:23:57 -05:00
# 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.
2019-02-11 15:44:25 -05:00
Zeitwerk :: Loader . eager_load_all if defined? ( Zeitwerk )
2012-08-01 14:54:22 -04:00
config . eager_load_namespaces . each ( & :eager_load! )
2010-05-15 17:48:56 -04:00
end
end
2011-12-12 09:18:19 -05:00
# All initialization is done, including eager loading in production
2010-05-15 17:48:56 -04:00
initializer :finisher_hook do
ActiveSupport . run_load_hooks ( :after_initialize , self )
2010-01-23 10:07:20 -05:00
end
2016-04-04 16:41:28 -04:00
class MutexHook
def initialize ( mutex = Mutex . new )
@mutex = mutex
end
def run
@mutex . lock
end
def complete ( _state )
@mutex . unlock
end
end
module InterlockHook
def self . run
ActiveSupport :: Dependencies . interlock . start_running
end
def self . complete ( _state )
ActiveSupport :: Dependencies . interlock . done_running
end
end
2016-02-21 20:25:52 -05:00
initializer :configure_executor_for_concurrency do | app |
if config . allow_concurrency == false
# User has explicitly opted out of concurrent request
# handling: presumably their code is not threadsafe
2016-04-04 16:41:28 -04:00
app . executor . register_hook ( MutexHook . new , outer : true )
2016-02-21 20:25:52 -05:00
elsif config . allow_concurrency == :unsafe
# Do nothing, even if we know this is dangerous. This is the
2016-05-27 22:10:45 -04:00
# historical behavior for true.
2016-02-21 20:25:52 -05:00
else
# Default concurrency setting: enabled, but safe
unless config . cache_classes && config . eager_load
# Without cache_classes + eager_load, the load interlock
# is required for proper operation
2016-04-04 16:41:28 -04:00
app . executor . register_hook ( InterlockHook , outer : true )
2016-02-21 20:25:52 -05:00
end
end
end
2013-06-06 17:04:26 -04:00
# Set routes reload after the finisher hook to ensure routes added in
# the hook are taken into account.
2016-02-21 20:25:52 -05:00
initializer :set_routes_reloader_hook do | app |
2011-12-13 03:25:12 -05:00
reloader = routes_reloader
2017-01-11 08:50:42 -05:00
reloader . eager_load = app . config . eager_load
2018-06-19 17:25:39 -04:00
reloader . execute
2016-08-07 19:05:28 -04:00
reloaders << reloader
2016-02-21 20:25:52 -05:00
app . reloader . to_run do
2013-06-06 17:04:26 -04:00
# We configure #execute rather than #execute_if_updated because if
# autoloaded constants are cleared we need to reload routes also in
# case any was used there, as in
#
# mount MailPreview => 'mail_view'
#
# This means routes are also reloaded if i18n is updated, which
# might not be necessary, but in order to be more precise we need
# some sort of reloaders dependency support, to be added.
2016-02-21 20:25:52 -05:00
require_unload_lock!
2013-06-06 17:04:26 -04:00
reloader . execute
end
2010-09-02 06:54:16 -04:00
end
2013-06-06 17:04:26 -04:00
# Set clearing dependencies after the finisher hook to ensure paths
# added in the hook are taken into account.
2016-02-21 20:25:52 -05:00
initializer :set_clear_dependencies_hook , group : :all do | app |
2011-12-13 03:25:12 -05:00
callback = lambda do
2016-02-21 20:25:52 -05:00
ActiveSupport :: DescendantsTracker . clear
ActiveSupport :: Dependencies . clear
end
if config . cache_classes
app . reloader . check = lambda { false }
elsif config . reload_classes_only_on_change
app . reloader . check = lambda do
app . reloaders . map ( & :updated? ) . any?
2014-09-29 12:16:07 -04:00
end
2016-02-21 20:25:52 -05:00
else
app . reloader . check = lambda { true }
2011-12-13 03:25:12 -05:00
end
2019-09-16 13:31:56 -04:00
if config . cache_classes
# No reloader
elsif config . reload_classes_only_on_change
2011-12-13 05:23:21 -05:00
reloader = config . file_watcher . new ( * watchable_args , & callback )
2016-08-07 19:05:28 -04:00
reloaders << reloader
2013-06-06 17:04:26 -04:00
# Prepend this callback to have autoloaded constants cleared before
# any other possible reloading, in case they need to autoload fresh
# constants.
2016-02-21 20:25:52 -05:00
app . reloader . to_run ( prepend : true ) do
2013-06-06 17:04:26 -04:00
# In addition to changes detected by the file watcher, if routes
# or i18n have been updated we also need to clear constants,
# that's why we run #execute rather than #execute_if_updated, this
# callback has to clear autoloaded constants after any update.
2016-02-21 20:25:52 -05:00
class_unload! do
reloader . execute
end
2013-06-06 17:04:26 -04:00
end
2011-12-13 03:25:12 -05:00
else
2016-02-21 20:25:52 -05:00
app . reloader . to_complete do
class_unload! ( & callback )
end
2011-12-13 03:25:12 -05:00
end
2011-12-12 16:51:33 -05:00
end
2015-02-16 18:03:37 -05:00
# Disable dependency loading during request cycle
initializer :disable_dependency_loading do
2016-06-22 13:09:27 -04:00
if config . eager_load && config . cache_classes && ! config . enable_dependency_loading
2015-02-16 18:03:37 -05:00
ActiveSupport :: Dependencies . unhook!
end
end
2010-01-23 10:07:20 -05:00
end
end
2010-03-20 13:34:21 -04:00
end