diff options
Diffstat (limited to 'railties/lib/rails/application.rb')
-rw-r--r-- | railties/lib/rails/application.rb | 273 |
1 files changed, 205 insertions, 68 deletions
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 82fffe86bb..ae872f2bb0 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,7 +1,4 @@ -require 'active_support/core_ext/hash/reverse_merge' -require 'active_support/file_update_checker' require 'fileutils' -require 'rails/plugin' require 'rails/engine' module Rails @@ -10,7 +7,7 @@ module Rails # # == Initialization # - # Rails::Application is responsible for executing all railties, engines and plugin + # Rails::Application is responsible for executing all railties and engines # initializers. It also executes some bootstrap initializers (check # Rails::Application::Bootstrap) and finishing initializers, after all the others # are executed (check Rails::Application::Finisher). @@ -19,8 +16,8 @@ module Rails # # Besides providing the same configuration as Rails::Engine and Rails::Railtie, # the application object has several specific configurations, for example - # "allow_concurrency", "cache_classes", "consider_all_requests_local", "filter_parameters", - # "logger", "reload_plugins" and so forth. + # "cache_classes", "consider_all_requests_local", "filter_parameters", + # "logger" and so forth. # # Check Rails::Application::Configuration to see them all. # @@ -33,11 +30,29 @@ module Rails # # The Application is also responsible for building the middleware stack. # + # == Booting process + # + # The application is also responsible for setting up and executing the booting + # process. From the moment you require "config/application.rb" in your app, + # the booting process goes like this: + # + # 1) require "config/boot.rb" to setup load paths + # 2) require railties and engines + # 3) Define Rails.application as "class MyApp::Application < Rails::Application" + # 4) Run config.before_configuration callbacks + # 5) Load config/environments/ENV.rb + # 6) Run config.before_initialize callbacks + # 7) Run Railtie#initializer defined by railties, engines and application. + # One by one, each engine sets up its load paths, routes and runs its config/initializers/* files. + # 9) Custom Railtie#initializers added by railties, engines and applications are executed + # 10) Build the middleware stack and run to_prepare callbacks + # 11) Run config.before_eager_load and eager_load if cache classes is true + # 12) Run config.after_initialize callbacks + # class Application < Engine autoload :Bootstrap, 'rails/application/bootstrap' autoload :Configuration, 'rails/application/configuration' autoload :Finisher, 'rails/application/finisher' - autoload :Railties, 'rails/application/railties' autoload :RoutesReloader, 'rails/application/routes_reloader' class << self @@ -50,16 +65,67 @@ module Rails end end - attr_accessor :assets, :sandbox + attr_accessor :assets, :sandbox, :queue_consumer alias_method :sandbox?, :sandbox + attr_reader :reloaders + attr_writer :queue delegate :default_url_options, :default_url_options=, :to => :routes def initialize super - @initialized = false + @initialized = false + @reloaders = [] + @routes_reloader = nil + @env_config = nil + @ordered_railties = nil + @railties = nil + @queue = nil + end + + # Returns true if the application is initialized. + def initialized? + @initialized + end + + # Implements call according to the Rack API. It simples + # dispatch the request to the underlying middleware stack. + def call(env) + env["ORIGINAL_FULLPATH"] = build_original_fullpath(env) + super(env) + end + + # Reload application routes regardless if they changed or not. + def reload_routes! + routes_reloader.reload! end + # Stores some of the Rails initial environment parameters which + # will be used by middlewares and engines to configure themselves. + # Currently stores: + # + # * "action_dispatch.parameter_filter" => config.filter_parameters, + # * "action_dispatch.secret_token" => config.secret_token, + # * "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions, + # * "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local, + # * "action_dispatch.logger" => Rails.logger, + # * "action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner + # + # These parameters will be used by middlewares and engines to configure themselves + # + def env_config + @env_config ||= super.merge({ + "action_dispatch.parameter_filter" => config.filter_parameters, + "action_dispatch.secret_token" => config.secret_token, + "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions, + "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local, + "action_dispatch.logger" => Rails.logger, + "action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner + }) + end + + ## Rails internal API + # This method is called just after an application inherits from Rails::Application, # allowing the developer to load classes in lib and use them during application # configuration. @@ -74,7 +140,7 @@ module Rails # Rails application, you will need to add lib to $LOAD_PATH on your own in case # you need to load files in lib/ during the application configuration as well. def add_lib_to_load_path! #:nodoc: - path = config.root.join('lib').to_s + path = File.join config.root, 'lib' $LOAD_PATH.unshift(path) if File.exists?(path) end @@ -83,105 +149,180 @@ module Rails require environment if environment end - def reload_routes! - routes_reloader.reload! + def routes_reloader #:nodoc: + @routes_reloader ||= RoutesReloader.new end - def routes_reloader - @routes_reloader ||= RoutesReloader.new + # Returns an array of file paths appended with a hash of + # directories-extensions suitable for ActiveSupport::FileUpdateChecker + # API. + def watchable_args #:nodoc: + files, dirs = config.watchable_files.dup, config.watchable_dirs.dup + + ActiveSupport::Dependencies.autoload_paths.each do |path| + dirs[path.to_s] = [:rb] + end + + [files, dirs] end - def initialize!(group=:default) + # Initialize the application passing the given group. By default, the + # group is :default but sprockets precompilation passes group equals + # to assets if initialize_on_precompile is false to avoid booting the + # whole app. + def initialize!(group=:default) #:nodoc: raise "Application has been already initialized." if @initialized run_initializers(group, self) @initialized = true self end - def load_tasks(app=self) - initialize_tasks - super - self + def initializers #:nodoc: + Bootstrap.initializers_for(self) + + railties_initializers(super) + + Finisher.initializers_for(self) end - def load_console(app=self) - initialize_console - super - self + def config #:nodoc: + @config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd)) end - # Rails.application.env_config stores some of the Rails initial environment parameters. - # Currently stores: - # - # * action_dispatch.parameter_filter" => config.filter_parameters, - # * action_dispatch.secret_token" => config.secret_token, - # * action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions - # - # These parameters will be used by middlewares and engines to configure themselves. - # - def env_config - @env_config ||= super.merge({ - "action_dispatch.parameter_filter" => config.filter_parameters, - "action_dispatch.secret_token" => config.secret_token, - "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions - }) + def queue #:nodoc: + @queue ||= Queueing::Container.new(build_queue) end - def initializers - Bootstrap.initializers_for(self) + - super + - Finisher.initializers_for(self) + def build_queue #:nodoc: + config.queue.new end - def config - @config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd)) + def to_app #:nodoc: + self end - def to_app - self + def helpers_paths #:nodoc: + config.helpers_paths + end + + def railties #:nodoc: + @railties ||= Rails::Railtie.subclasses.map(&:instance) + + Rails::Engine.subclasses.map(&:instance) end protected alias :build_middleware_stack :app - def default_middleware_stack + def run_tasks_blocks(app) #:nodoc: + railties.each { |r| r.run_tasks_blocks(app) } + super + require "rails/tasks" + config = self.config + task :environment do + config.eager_load = false + require_environment! + end + end + + def run_generators_blocks(app) #:nodoc: + railties.each { |r| r.run_generators_blocks(app) } + super + end + + def run_runner_blocks(app) #:nodoc: + railties.each { |r| r.run_runner_blocks(app) } + super + end + + def run_console_blocks(app) #:nodoc: + railties.each { |r| r.run_console_blocks(app) } + super + end + + # Returns the ordered railties for this application considering railties_order. + def ordered_railties #:nodoc: + @ordered_railties ||= begin + order = config.railties_order.map do |railtie| + if railtie == :main_app + self + elsif railtie.respond_to?(:instance) + railtie.instance + else + railtie + end + end + + all = (railties - order) + all.push(self) unless (all + order).include?(self) + order.push(:all) unless order.include?(:all) + + index = order.index(:all) + order[index] = all + order.reverse.flatten + end + end + + def railties_initializers(current) #:nodoc: + initializers = [] + ordered_railties.each do |r| + if r == self + initializers += current + else + initializers += r.initializers + end + end + initializers + end + + def reload_dependencies? #:nodoc: + config.reload_classes_only_on_change != true || reloaders.map(&:updated?).any? + end + + def default_middleware_stack #:nodoc: ActionDispatch::MiddlewareStack.new.tap do |middleware| + app = self if rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache require "action_dispatch/http/rack_cache" middleware.use ::Rack::Cache, rack_cache end if config.force_ssl - require "rack/ssl" - middleware.use ::Rack::SSL, config.ssl_options + middleware.use ::ActionDispatch::SSL, config.ssl_options + end + + if config.action_dispatch.x_sendfile_header.present? + middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header end if config.serve_static_assets middleware.use ::ActionDispatch::Static, paths["public"].first, config.static_cache_control end - middleware.use ::Rack::Lock unless config.allow_concurrency + middleware.use ::Rack::Lock unless config.cache_classes middleware.use ::Rack::Runtime middleware.use ::Rack::MethodOverride middleware.use ::ActionDispatch::RequestId middleware.use ::Rails::Rack::Logger, config.log_tags # must come after Rack::MethodOverride to properly log overridden methods - middleware.use ::ActionDispatch::ShowExceptions, config.consider_all_requests_local + middleware.use ::ActionDispatch::ShowExceptions, config.exceptions_app || ActionDispatch::PublicExceptions.new(Rails.public_path) + middleware.use ::ActionDispatch::DebugExceptions, app middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies - if config.action_dispatch.x_sendfile_header.present? - middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header + + unless config.cache_classes + middleware.use ::ActionDispatch::Reloader, lambda { app.reload_dependencies? } end - middleware.use ::ActionDispatch::Reloader unless config.cache_classes + middleware.use ::ActionDispatch::Callbacks middleware.use ::ActionDispatch::Cookies if config.session_store + if config.force_ssl && !config.session_options.key?(:secure) + config.session_options[:secure] = true + end middleware.use config.session_store, config.session_options middleware.use ::ActionDispatch::Flash end middleware.use ::ActionDispatch::ParamsParser - middleware.use ::ActionDispatch::Head + middleware.use ::Rack::Head middleware.use ::Rack::ConditionalGet middleware.use ::Rack::ETag, "no-cache" @@ -191,20 +332,16 @@ module Rails end end - def initialize_tasks - self.class.rake_tasks do - require "rails/tasks" - task :environment do - $rails_rake_task = true - require_environment! - end - end - end + def build_original_fullpath(env) #:nodoc: + path_info = env["PATH_INFO"] + query_string = env["QUERY_STRING"] + script_name = env["SCRIPT_NAME"] - def initialize_console - require "pp" - require "rails/console/app" - require "rails/console/helpers" + if query_string.present? + "#{script_name}#{path_info}?#{query_string}" + else + "#{script_name}#{path_info}" + end end end end |