提交 7fcf8590 编写于 作者: J José Valim

Massive cleanup in Railties and load stack.

上级 2df1810c
......@@ -19,12 +19,6 @@ class Railtie < Rails::Railtie
ActionController::Base.logger ||= Rails.logger
end
# Routing must be initialized after plugins to allow the former to extend the routes
initializer "action_controller.initialize_routing" do |app|
app.route_configuration_files << app.config.routes_configuration_file
app.route_configuration_files << app.config.builtin_routes_configuration_file
end
initializer "action_controller.initialize_framework_caches" do
ActionController::Base.cache_store ||= RAILS_CACHE
end
......
......@@ -5,9 +5,10 @@
require 'active_support/core_ext/logger'
require 'rails/initializable'
require 'rails/application'
require 'rails/railtie'
require 'rails/plugin'
require 'rails/engine'
require 'rails/application'
require 'rails/railties_path'
require 'rails/version'
require 'rails/rack'
......
require "fileutils"
require 'active_support/core_ext/module/delegation'
module Rails
class Application
class Application < Engine
include Initializable
class << self
attr_writer :config
alias configure class_eval
delegate :initialize!, :load_tasks, :load_generators, :root, :to => :instance
alias :configure :class_eval
delegate :initialize!, :load_tasks, :load_generators, :to => :instance
private :new
def instance
......@@ -16,7 +14,16 @@ def instance
end
def config
@config ||= Configuration.new(Plugin::Configuration.default)
@config ||= Configuration.new(root)
end
def root
@root ||= find_root_with_file_flag("config.ru", Dir.pwd)
end
def inherited(base)
super
Railtie.plugins.delete(base)
end
def routes
......@@ -24,8 +31,7 @@ def routes
end
end
delegate :config, :routes, :to => :'self.class'
delegate :root, :middleware, :to => :config
delegate :routes, :to => :'self.class'
attr_reader :route_configuration_files
def initialize
......@@ -38,12 +44,7 @@ def initialize!
run_initializers(self)
self
end
def require_environment
require config.environment_path
rescue LoadError
end
def routes_changed_at
routes_changed_at = nil
......@@ -59,6 +60,7 @@ def routes_changed_at
end
def reload_routes!
routes = Rails::Application.routes
routes.disable_clear_and_finalize = true
routes.clear!
......@@ -70,6 +72,12 @@ def reload_routes!
routes.disable_clear_and_finalize = false
end
def require_environment
require config.environment_path
rescue LoadError
end
def load_tasks
require "rails/tasks"
plugins.each { |p| p.load_tasks }
......@@ -114,37 +122,23 @@ def call(env)
app.call(env)
end
initializer :load_application_initializers do
Dir["#{root}/config/initializers/**/*.rb"].sort.each do |initializer|
load(initializer)
end
initializer :build_middleware_stack, :after => :load_application_initializers do
app
end
initializer :build_middleware_stack do
app
initializer :add_builtin_route do |app|
if Rails.env.development?
app.route_configuration_files << File.join(RAILTIES_PATH, 'builtin', 'routes.rb')
end
end
# Fires the user-supplied after_initialize block (Configuration#after_initialize)
initializer :after_initialize do
initializer :after_initialize, :after => :build_middleware_stack do
config.after_initialize_blocks.each do |block|
block.call
end
end
# Eager load application classes
initializer :load_application_classes do
next if $rails_rake_task
if config.cache_classes
config.eager_load_paths.each do |load_path|
matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/
Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
require_dependency file.sub(matcher, '\1')
end
end
end
end
# Disable dependency loading during request cycle
initializer :disable_dependency_loading do
if config.cache_classes && !config.dependency_loading
......
......@@ -12,30 +12,25 @@ def initialize(application)
require "active_support/all" unless config.active_support.bare
end
# Set the <tt>$LOAD_PATH</tt> based on the value of
# Configuration#load_paths. Duplicates are removed.
initializer :set_load_path do
config.paths.add_to_load_path
$LOAD_PATH.uniq!
end
# Set the paths from which Rails will automatically load source files, and
# the load_once paths.
initializer :set_autoload_paths do
require 'active_support/dependencies'
ActiveSupport::Dependencies.load_paths = expand_load_path(config.load_paths)
ActiveSupport::Dependencies.load_once_paths = expand_load_path(config.load_once_paths)
extra = ActiveSupport::Dependencies.load_once_paths - ActiveSupport::Dependencies.load_paths
unless extra.empty?
abort <<-end_error
load_once_paths must be a subset of the load_paths.
Extra items in load_once_paths: #{extra * ','}
end_error
initializer :initialize_logger do
Rails.logger ||= config.logger || begin
logger = ActiveSupport::BufferedLogger.new(config.paths.log.to_a.first)
logger.level = ActiveSupport::BufferedLogger.const_get(config.log_level.to_s.upcase)
logger.auto_flushing = false if Rails.env.production?
logger
rescue StandardError => e
logger = ActiveSupport::BufferedLogger.new(STDERR)
logger.level = ActiveSupport::BufferedLogger::WARN
logger.warn(
"Rails Error: Unable to access log file. Please ensure that #{config.log_path} exists and is chmod 0666. " +
"The log level has been raised to WARN and the output directed to STDERR until the problem is fixed."
)
logger
end
end
# Freeze the arrays so future modifications will fail rather than do nothing mysteriously
config.load_once_paths.freeze
initializer :container do
# FIXME This is just a dumb initializer used as hook
end
# Create tmp directories
......@@ -63,29 +58,6 @@ def initialize(application)
end
end
initializer :initialize_logger do
Rails.logger ||= config.logger || begin
logger = ActiveSupport::BufferedLogger.new(config.log_path)
logger.level = ActiveSupport::BufferedLogger.const_get(config.log_level.to_s.upcase)
logger.auto_flushing = false if Rails.env.production?
logger
rescue StandardError => e
logger = ActiveSupport::BufferedLogger.new(STDERR)
logger.level = ActiveSupport::BufferedLogger::WARN
logger.warn(
"Rails Error: Unable to access log file. Please ensure that #{config.log_path} exists and is chmod 0666. " +
"The log level has been raised to WARN and the output directed to STDERR until the problem is fixed."
)
logger
end
end
# Sets the logger for dependencies and cache store.
initializer :initialize_framework_logging do
ActiveSupport::Dependencies.logger ||= Rails.logger
Rails.cache.logger ||= Rails.logger
end
# Sets the dependency loading mechanism based on the value of
# Configuration#cache_classes.
initializer :initialize_dependency_mechanism do
......
require 'active_support/ordered_options'
module Rails
# Temporarily separate the plugin configuration class from the main
# configuration class while this bit is being cleaned up.
class Railtie::Configuration
def self.default
@default ||= new
end
def self.default_middleware_stack
ActionDispatch::MiddlewareStack.new.tap do |middleware|
module SharedConfiguration
def self.middleware_stack
@default_middleware_stack ||= ActionDispatch::MiddlewareStack.new.tap do |middleware|
middleware.use('::ActionDispatch::Static', lambda { Rails.public_path }, :if => lambda { Rails.application.config.serve_static_assets })
middleware.use('::Rack::Lock', :if => lambda { !ActionController::Base.allow_concurrency })
middleware.use('::Rack::Runtime')
......@@ -26,16 +20,23 @@ def self.default_middleware_stack
end
end
def self.options
@options ||= Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new }
end
end
# Temporarily separate the plugin configuration class from the main
# configuration class while this bit is being cleaned up.
class Railtie::Configuration
def self.default
@default ||= new
end
attr_reader :middleware
def initialize(base = nil)
if base
@options = base.options.dup
@middleware = base.middleware.dup
else
@options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new }
@middleware = self.class.default_middleware_stack
end
def initialize
@options = SharedConfiguration.options
@middleware = SharedConfiguration.middleware_stack
end
def respond_to?(name)
......@@ -61,27 +62,65 @@ def config_key_regexp
/^(#{bits})(?:=)?$/
end
# TODO Remove :active_support as special case by adding a railtie
# for it and for I18n
def config_keys
([ :active_support, :action_view ] +
Railtie.plugin_names).map { |n| n.to_s }.uniq
([:active_support] + Railtie.plugin_names).map { |n| n.to_s }.uniq
end
end
class Configuration < Railtie::Configuration
class Engine::Configuration < Railtie::Configuration
attr_reader :root
def initialize(root)
@root = root
super()
end
def paths
@paths ||= begin
paths = Rails::Application::Root.new(root)
paths.app "app", :load_path => true
paths.app_glob "app/*", :load_path => true, :eager_load => true
paths.app.controllers "app/controllers"
paths.app.metals "app/metal"
paths.app.views "app/views"
paths.lib "lib", :load_path => true
paths.config "config"
paths.config.environments "config/environments", :glob => "#{Rails.env}.rb"
paths.config.initializers "config/initializers"
paths.config.locales "config/locales"
paths.config.routes "config/routes.rb"
paths
end
end
def eager_load_paths
@eager_load_paths ||= paths.eager_load
end
def load_once_paths
@eager_load_paths ||= paths.load_once
end
def load_paths
@load_paths ||= paths.load_paths
end
end
class Configuration < Engine::Configuration
attr_accessor :after_initialize_blocks, :cache_classes, :colorize_logging,
:consider_all_requests_local, :dependency_loading, :filter_parameters,
:load_once_paths, :logger, :metals, :plugins,
:logger, :metals, :plugins,
:preload_frameworks, :reload_plugins, :serve_static_assets,
:time_zone, :whiny_nils
attr_writer :cache_store, :controller_paths,
:database_configuration_file, :eager_load_paths,
:i18n, :load_paths, :log_level, :log_path, :paths,
:routes_configuration_file, :view_path
:database_configuration_file,
:i18n, :log_level, :log_path
def initialize(base = nil)
def initialize(*)
super
@load_once_paths = []
@after_initialize_blocks = []
@filter_parameters = []
@dependency_loading = true
......@@ -92,46 +131,23 @@ def after_initialize(&blk)
@after_initialize_blocks << blk if blk
end
def root
@root ||= begin
call_stack = caller.map { |p| p.split(':').first }
root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] }
root_path = File.dirname(root_path)
while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/config.ru")
parent = File.dirname(root_path)
root_path = parent != root_path && parent
end
root = File.exist?("#{root_path}/config.ru") ? root_path : Dir.pwd
RUBY_PLATFORM =~ /(:?mswin|mingw)/ ?
Pathname.new(root).expand_path :
Pathname.new(root).realpath
end
end
def root=(root)
@root = Pathname.new(root).expand_path
end
def paths
@paths ||= begin
paths = Rails::Application::Root.new(root)
paths.app "app", :load_path => true
paths.app.metals "app/metal", :eager_load => true
paths.app.models "app/models", :eager_load => true
paths.app.controllers "app/controllers", builtin_directories, :eager_load => true
paths.app.helpers "app/helpers", :eager_load => true
paths.app.services "app/services", :load_path => true
paths.lib "lib", :load_path => true
paths.vendor "vendor", :load_path => true
paths.vendor.plugins "vendor/plugins"
paths.tmp "tmp"
paths.tmp.cache "tmp/cache"
paths.config "config"
paths.config.locales "config/locales"
paths.config.environments "config/environments", :glob => "#{Rails.env}.rb"
paths = super
paths.builtin_controller builtin_directories, :eager_load => true
paths.config.database "config/database.yml"
paths.log "log/#{Rails.env}.log"
paths.tmp "tmp"
paths.tmp.cache "tmp/cache"
paths.vendor "vendor", :load_path => true
paths.vendor.plugins "vendor/plugins"
if File.exists?("#{root}/test/mocks/#{Rails.env}")
ActiveSupport::Deprecation.warn "\"RAILS_ROOT/test/mocks/#{Rails.env}\" won't be added " <<
"automatically to load paths anymore in next releases."
paths.mocks_path "test/mocks/#{Rails.env}", :load_path => true
end
paths
end
end
......@@ -163,17 +179,61 @@ def threadsafe!
# YAML::load.
def database_configuration
require 'erb'
YAML::load(ERB.new(IO.read(database_configuration_file)).result)
YAML::load(ERB.new(IO.read(paths.config.database.to_a.first)).result)
end
def view_path=(value)
ActiveSupport::Deprecation.warn "config.view_path= is deprecated, " <<
"please do config.paths.app.views= instead", caller
paths.app.views = value
end
def view_path
ActiveSupport::Deprecation.warn "config.view_path is deprecated, " <<
"please do config.paths.app.views instead", caller
paths.app.views.to_a.first
end
def routes_configuration_file=(value)
ActiveSupport::Deprecation.warn "config.routes_configuration_file= is deprecated, " <<
"please do config.paths.config.routes= instead", caller
paths.config.routes = value
end
def routes_configuration_file
@routes_configuration_file ||= File.join(root, 'config', 'routes.rb')
ActiveSupport::Deprecation.warn "config.routes_configuration_file is deprecated, " <<
"please do config.paths.config.routes instead", caller
paths.config.routes.to_a.first
end
def database_configuration_file=(value)
ActiveSupport::Deprecation.warn "config.database_configuration_file= is deprecated, " <<
"please do config.paths.config.database= instead", caller
paths.config.database = value
end
def database_configuration_file
ActiveSupport::Deprecation.warn "config.database_configuration_file is deprecated, " <<
"please do config.paths.config.database instead", caller
paths.config.database.to_a.first
end
def log_path=(value)
ActiveSupport::Deprecation.warn "config.log_path= is deprecated, " <<
"please do config.paths.log= instead", caller
paths.config.log = value
end
def builtin_routes_configuration_file
@builtin_routes_configuration_file ||= File.join(RAILTIES_PATH, 'builtin', 'routes.rb')
def log_path
ActiveSupport::Deprecation.warn "config.log_path is deprecated, " <<
"please do config.paths.log instead", caller
paths.config.log.to_a.first
end
# TODO Router needs this, but this wouldn't work with engines.
# There is a high chance of plugins routes to be broken.
def controller_paths
@controller_paths ||= begin
paths = [File.join(root, 'app', 'controllers')]
......@@ -192,46 +252,11 @@ def cache_store
end
end
def database_configuration_file
@database_configuration_file ||= File.join(root, 'config', 'database.yml')
end
def view_path
@view_path ||= File.join(root, 'app', 'views')
end
def eager_load_paths
@eager_load_paths ||= ["#{root}/app/*"]
end
def load_paths
@load_paths ||= begin
paths = []
# Add the old mock paths only if the directories exists
paths.concat(Dir["#{root}/test/mocks/#{Rails.env}"]) if File.exists?("#{root}/test/mocks/#{Rails.env}")
# Followed by the standard includes.
paths.concat %w(
app
app/*
lib
vendor
).map { |dir| "#{root}/#{dir}" }
paths.concat builtin_directories
end
end
# Include builtins only in the development environment.
def builtin_directories
# Include builtins only in the development environment.
Rails.env.development? ? Dir["#{RAILTIES_PATH}/builtin/*/"] : []
end
def log_path
@log_path ||= File.join(root, 'log', "#{Rails.env}.log")
end
def log_level
@log_level ||= Rails.env.production? ? :info : :debug
end
......
require 'active_support/core_ext/module/delegation'
module Rails
# TODO Move I18n and views path setup
class Engine < Railtie
class << self
attr_accessor :called_from
def root
@root ||= find_root_with_file_flag("lib")
end
def config
@config ||= Configuration.new(root)
end
def inherited(base)
base.called_from = begin
call_stack = caller.map { |p| p.split(':').first }
File.dirname(call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] })
end
super
end
protected
def find_root_with_file_flag(flag, default=nil)
root_path = self.called_from
while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/#{flag}")
parent = File.dirname(root_path)
root_path = parent != root_path && parent
end
root = File.exist?("#{root_path}/flag") ? root_path : default
raise "Could not find root path for #{self}" unless root
RUBY_PLATFORM =~ /(:?mswin|mingw)/ ?
Pathname.new(root).expand_path :
Pathname.new(root).realpath
end
end
delegate :root, :config, :to => :'self.class'
delegate :middleware, :to => :config
# Add configured load paths to ruby load paths and remove duplicates.
initializer :set_load_path, :before => :container do
config.paths.add_to_load_path
$LOAD_PATH.uniq!
end
# Set the paths from which Rails will automatically load source files,
# and the load_once paths.
initializer :set_autoload_paths, :before => :container do
require 'active_support/dependencies'
ActiveSupport::Dependencies.load_paths = expand_load_path(config.load_paths)
ActiveSupport::Dependencies.load_once_paths = expand_load_path(config.load_once_paths)
extra = ActiveSupport::Dependencies.load_once_paths - ActiveSupport::Dependencies.load_paths
unless extra.empty?
abort <<-end_error
load_once_paths must be a subset of the load_paths.
Extra items in load_once_paths: #{extra * ','}
end_error
end
# Freeze the arrays so future modifications will fail rather than do nothing mysteriously
config.load_once_paths.freeze
end
initializer :load_application_initializers do
Dir["#{root}/config/initializers/**/*.rb"].sort.each do |initializer|
load(initializer)
end
end
# Routing must be initialized after plugins to allow the former to extend the routes
initializer :initialize_routing do |app|
app.route_configuration_files.concat(config.paths.config.routes.to_a)
end
# Eager load application classes
initializer :load_application_classes do |app|
next if $rails_rake_task
if app.config.cache_classes
config.eager_load_paths.each do |load_path|
matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/
Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
require_dependency file.sub(matcher, '\1')
end
end
end
end
private
def expand_load_path(load_paths)
load_paths.map { |path| Dir.glob(path.to_s) }.flatten.uniq
end
end
end
\ No newline at end of file
......@@ -57,7 +57,6 @@ def load_tasks
end
end
# TODO Isn't it supposed to be :after => "action_controller.initialize_routing" ?
initializer :add_routing_file, :after => :initialize_routing do |app|
routing_file = "#{path}/config/routes.rb"
if File.exist?(routing_file)
......
......@@ -2,43 +2,51 @@ module Rails
class Railtie
include Initializable
def self.plugin_name(plugin_name = nil)
@plugin_name ||= name.demodulize.underscore
@plugin_name = plugin_name if plugin_name
@plugin_name
end
ABSTRACT_RAILTIES = %w(Rails::Plugin Rails::Engine Rails::Application)
def self.inherited(klass)
@plugins ||= []
@plugins << klass unless klass == Plugin
end
class << self
def abstract_railtie?(base)
ABSTRACT_RAILTIES.include?(base.name)
end
def self.plugins
@plugins
end
def inherited(base)
@@plugins ||= []
@@plugins << base unless abstract_railtie?(base)
end
def self.plugin_names
plugins.map { |p| p.plugin_name }
end
def plugin_name(plugin_name = nil)
@plugin_name ||= name.demodulize.underscore
@plugin_name = plugin_name if plugin_name
@plugin_name
end
def self.config
Configuration.default
end
def plugins
@@plugins
end
def self.subscriber(subscriber)
Rails::Subscriber.add(plugin_name, subscriber)
end
def plugin_names
plugins.map { |p| p.plugin_name }
end
def self.rake_tasks(&blk)
@rake_tasks ||= []
@rake_tasks << blk if blk
@rake_tasks
end
def config
Configuration.default
end
def subscriber(subscriber)
Rails::Subscriber.add(plugin_name, subscriber)
end
def rake_tasks(&blk)
@rake_tasks ||= []
@rake_tasks << blk if blk
@rake_tasks
end
def self.generators(&blk)
@generators ||= []
@generators << blk if blk
@generators
def generators(&blk)
@generators ||= []
@generators << blk if blk
@generators
end
end
def rake_tasks
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册