From 6a3f8ae4075042f122d493208f18ecfb797b38ae Mon Sep 17 00:00:00 2001 From: Tim Connor Date: Thu, 21 May 2009 14:51:34 -0700 Subject: Work around a gem dependency edge case that prevents Rails from booting.. If you have a frozen gem with unfrozen dependencies (for instance if the dependency has native extensions so can't be frozen) you can have a nightmare upgrade problem, where you cannot rake gems:install, because rake is broken by a gem loading problem. If you bump up your frozen gem to a newer version that requires a newer dependency, everybody else on the team will have rake broken by that dependency mismatch, since you will have had to specify the dependency in your config.gems, otherwise nobody will have installed it, since the parent is frozen. And now the config.gems loading code will kill rake. [#2609 state:committed] Signed-off-by: Jeremy Kemper --- railties/lib/initializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 7273cea0c5..9148bddaf2 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -304,7 +304,7 @@ module Rails end def load_gems - unless $gems_build_rake_task + unless $gems_rake_task @configuration.gems.each { |gem| gem.load } end end -- cgit v1.2.3 From 41a94048e55e082f373e19d9fcee311860aaba9e Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Sat, 6 Jun 2009 17:59:33 -0400 Subject: Fix several issues with the 2.3.2 gem loader. Incorporates the following: - migrates back small change to gems:build:force from bfc1609a501fc3ed442685819de5bcdb5fbada1c to finish closing #2266. - unrolls to_proc calls in gems.rake, to match the change in master. - fixes #2722 by passing the options hash to dependencies during build. (includes a test) - fixes #2721 by loading the specification directly in from_directory_name. Adds an option to opt-out of specification loading when needed (in gems:refresh_specs, for instance). Includes tests. - fixes #2679 by refreshing specs for all frozen gems rather than just gems loaded from the environment. - fixes #2678 by passing the options hash to dependencies during unpack. Signed-off-by: Michael Koziarski --- railties/lib/rails/gem_dependency.rb | 20 ++++++++++++++++---- railties/lib/tasks/gems.rake | 14 +++++++------- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/gem_dependency.rb b/railties/lib/rails/gem_dependency.rb index ee3d0d81ba..3a82202bd0 100644 --- a/railties/lib/rails/gem_dependency.rb +++ b/railties/lib/rails/gem_dependency.rb @@ -29,11 +29,18 @@ module Rails end end - def self.from_directory_name(directory_name) + def self.from_directory_name(directory_name, load_spec=true) directory_name_parts = File.basename(directory_name).split('-') name = directory_name_parts[0..-2].join('-') version = directory_name_parts.last - self.new(name, :version => version) + result = self.new(name, :version => version) + spec_filename = File.join(unpacked_path, directory_name, '.specification') + if load_spec + raise "Missing specification file in #{File.dirname(spec_filename)}. Perhaps you need to do a 'rake gems:refresh_specs'?" unless File.exists?(spec_filename) + spec = YAML::load_file(spec_filename) + result.specification = spec + end + result rescue ArgumentError => e raise "Unable to determine gem name and version from '#{directory_name}'" end @@ -104,6 +111,10 @@ module Rails end end + def specification=(s) + @spec = s + end + def requirement r = version_requirements (r == Gem::Requirement.default) ? nil : r @@ -170,13 +181,14 @@ module Rails def build(options={}) require 'rails/gem_builder' + return if specification.nil? if options[:force] || !built? return unless File.exists?(unpacked_specification_filename) spec = YAML::load_file(unpacked_specification_filename) Rails::GemBuilder.new(spec, unpacked_gem_directory).build_extensions puts "Built gem: '#{unpacked_gem_directory}'" end - dependencies.each { |dep| dep.build } + dependencies.each { |dep| dep.build(options) } end def install @@ -236,7 +248,7 @@ module Rails real_spec = Gem::Specification.load(specification.loaded_from) write_specification(real_spec) end - dependencies.each { |dep| dep.unpack } if options[:recursive] + dependencies.each { |dep| dep.unpack(options) } if options[:recursive] end def write_specification(spec) diff --git a/railties/lib/tasks/gems.rake b/railties/lib/tasks/gems.rake index e496e1a04f..f1c34c7cca 100644 --- a/railties/lib/tasks/gems.rake +++ b/railties/lib/tasks/gems.rake @@ -20,7 +20,7 @@ namespace :gems do desc "Build any native extensions for unpacked gems" task :build do $gems_build_rake_task = true - frozen_gems.each {|gem| gem.build } + frozen_gems.each { |gem| gem.build } end namespace :build do @@ -33,12 +33,12 @@ namespace :gems do desc "Installs all required gems." task :install => :base do - current_gems.each {|gem| gem.install } + current_gems.each { |gem| gem.install } end desc "Unpacks all required gems into vendor/gems." task :unpack => :install do - current_gems.each {|gem| gem.unpack } + current_gems.each { |gem| gem.unpack } end namespace :unpack do @@ -49,8 +49,8 @@ namespace :gems do end desc "Regenerate gem specifications in correct format." - task :refresh_specs => :base do - current_gems.each {|gem| gem.refresh } + task :refresh_specs do + frozen_gems(false).each { |gem| gem.refresh } end end @@ -60,9 +60,9 @@ def current_gems gems end -def frozen_gems +def frozen_gems(load_specs=true) Dir[File.join(RAILS_ROOT, 'vendor', 'gems', '*-*')].map do |gem_dir| - Rails::GemDependency.from_directory_name(gem_dir) + Rails::GemDependency.from_directory_name(gem_dir, load_specs) end end -- cgit v1.2.3 From d7e0cb05cc8adad430d0e97efef1608eef58db80 Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Tue, 9 Jun 2009 12:26:52 -0400 Subject: Fix incorrect specification path in GemDependency#from_directory_name Signed-off-by: Michael Koziarski --- railties/lib/rails/gem_dependency.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/gem_dependency.rb b/railties/lib/rails/gem_dependency.rb index 3a82202bd0..3cc75494e4 100644 --- a/railties/lib/rails/gem_dependency.rb +++ b/railties/lib/rails/gem_dependency.rb @@ -34,7 +34,7 @@ module Rails name = directory_name_parts[0..-2].join('-') version = directory_name_parts.last result = self.new(name, :version => version) - spec_filename = File.join(unpacked_path, directory_name, '.specification') + spec_filename = File.join(directory_name, '.specification') if load_spec raise "Missing specification file in #{File.dirname(spec_filename)}. Perhaps you need to do a 'rake gems:refresh_specs'?" unless File.exists?(spec_filename) spec = YAML::load_file(spec_filename) -- cgit v1.2.3 From d8f352e970ec86e8b791f9994465a3678a44281f Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Wed, 17 Jun 2009 15:32:55 -0700 Subject: Rename ActionView::Template::Path ActionView::Resolver --- railties/lib/initializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 9148bddaf2..1aa71c31b5 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -401,7 +401,7 @@ Run `rake gems:install` to install the missing gems. def load_view_paths if configuration.frameworks.include?(:action_view) if configuration.cache_classes - view_path = ActionView::Template::FileSystemPath.new(configuration.view_path) + view_path = ActionView::FileSystemResolverWithFallback.new(configuration.view_path) ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) end -- cgit v1.2.3 From 54f48517708d16e92bfc6bab6255f6299ca80af0 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 18 Jun 2009 21:31:10 -0400 Subject: Turn on autolist for debugging also --- railties/lib/test_help.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/test_help.rb b/railties/lib/test_help.rb index 94e089a624..622b1f547c 100644 --- a/railties/lib/test_help.rb +++ b/railties/lib/test_help.rb @@ -29,7 +29,10 @@ end begin require_library_or_gem 'ruby-debug' Debugger.start - Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings) + if Debugger.respond_to?(:settings) + Debugger.settings[:autoeval] = true + Debugger.settings[:autolist] = 1 + end rescue LoadError # ruby-debug wasn't available so neither can the debugging be end -- cgit v1.2.3 From a3309e4d70101ec1b32064a99042622c43619d09 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 18 Jun 2009 17:44:35 -0700 Subject: Started making progress on implementing a new initializer. Class.any_instance.expects(:require).raises(LoadError) ... w0t --- railties/lib/initializer.rb | 1434 ++++++++++++--------------------------- railties/lib/initializer_old.rb | 1137 +++++++++++++++++++++++++++++++ 2 files changed, 1585 insertions(+), 986 deletions(-) create mode 100644 railties/lib/initializer_old.rb (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 1aa71c31b5..55fef30dbe 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -1,1137 +1,599 @@ -require 'logger' -require 'set' -require 'pathname' - -$LOAD_PATH.unshift File.dirname(__FILE__) -require 'railties_path' -require 'rails/version' -require 'rails/gem_dependency' -require 'rails/rack' - -RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) - module Rails - class << self - # The Configuration instance used to configure the Rails environment - def configuration - @@configuration - end - - def configuration=(configuration) - @@configuration = configuration - end + class Configuration + attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths, + :load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks, + :frameworks, :framework_root_path, :root_path - def initialized? - @initialized || false + def initialize + @framework_paths = [] + @load_once_paths = [] + @after_initialize_blocks = [] + @frameworks = [] end - def initialized=(initialized) - @initialized ||= initialized + def after_initialize(&blk) + @after_initialize_blocks << blk if blk end - def logger - if defined?(RAILS_DEFAULT_LOGGER) - RAILS_DEFAULT_LOGGER - else - nil - end - end + def framework_paths + paths = %w(railties railties/lib activesupport/lib) + paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) - def backtrace_cleaner - @@backtrace_cleaner ||= begin - # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded - require 'rails/backtrace_cleaner' - Rails::BacktraceCleaner.new + [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework| + paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework) end - end - def root - Pathname.new(RAILS_ROOT) if defined?(RAILS_ROOT) - end - - def env - @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) - end - - def cache - RAILS_CACHE - end - - def version - VERSION::STRING - end - - def public_path - @@public_path ||= self.root ? File.join(self.root, "public") : "public" + paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } end - def public_path=(path) - @@public_path = path + def framework_root_path + defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails" end end - # The Initializer is responsible for processing the Rails configuration, such - # as setting the $LOAD_PATH, requiring the right frameworks, initializing - # logging, and more. It can be run either as a single command that'll just - # use the default configuration, like this: - # - # Rails::Initializer.run - # - # But normally it's more interesting to pass in a custom configuration - # through the block running: - # - # Rails::Initializer.run do |config| - # config.frameworks -= [ :action_mailer ] - # end - # - # This will use the default configuration options from Rails::Configuration, - # but allow for overwriting on select areas. class Initializer - # The Configuration instance used by this Initializer instance. - attr_reader :configuration - - # The set of loaded plugins. - attr_reader :loaded_plugins - - # Whether or not all the gem dependencies have been met - attr_reader :gems_dependencies_loaded - - # Runs the initializer. By default, this will invoke the #process method, - # which simply executes all of the initialization routines. Alternately, - # you can specify explicitly which initialization routine you want: - # - # Rails::Initializer.run(:set_load_path) - # - # This is useful if you only want the load path initialized, without - # incurring the overhead of completely loading the entire environment. - def self.run(command = :process, configuration = Configuration.new) - yield configuration if block_given? - initializer = new configuration - initializer.send(command) - initializer - end - - # Create a new Initializer instance that references the given Configuration - # instance. - def initialize(configuration) - @configuration = configuration - @loaded_plugins = [] - end - - # Sequentially step through all of the available initialization routines, - # in order (view execution order in source). - def process - Rails.configuration = configuration - - check_ruby_version - install_gem_spec_stubs - set_load_path - add_gem_load_paths - - require_frameworks - set_autoload_paths - add_plugin_load_paths - load_environment - preload_frameworks - - initialize_encoding - initialize_database - - initialize_cache - initialize_framework_caches - - initialize_logger - initialize_framework_logging + class Error < StandardError ; end - initialize_dependency_mechanism - initialize_whiny_nils - - initialize_time_zone - initialize_i18n - - initialize_framework_settings - initialize_framework_views - - initialize_metal - - add_support_load_paths - - check_for_unbuilt_gems - - load_gems - load_plugins - - # pick up any gems that plugins depend on - add_gem_load_paths - load_gems - check_gem_dependencies - - # bail out if gems are missing - note that check_gem_dependencies will have - # already called abort() unless $gems_rake_task is set - return unless gems_dependencies_loaded - - load_application_initializers - - # the framework is now fully initialized - after_initialize - - # Setup database middleware after initializers have run - initialize_database_middleware - - # Prepare dispatcher callbacks and run 'prepare' callbacks - prepare_dispatcher - - # Routing must be initialized after plugins to allow the former to extend the routes - initialize_routing - - # Observers are loaded after plugins in case Observers or observed models are modified by plugins. - load_observers - - # Load view path cache - load_view_paths - - # Load application classes - load_application_classes - - # Disable dependency loading during request cycle - disable_dependency_loading - - # Flag initialized - Rails.initialized = true - end - - # Check for valid Ruby version - # This is done in an external file, so we can use it - # from the `rails` program as well without duplication. - def check_ruby_version - require 'ruby_version_check' - end - - # If Rails is vendored and RubyGems is available, install stub GemSpecs - # for Rails, Active Support, Active Record, Action Pack, Action Mailer, and - # Active Resource. This allows Gem plugins to depend on Rails even when - # the Gem version of Rails shouldn't be loaded. - def install_gem_spec_stubs - unless Rails.respond_to?(:vendor_rails?) - abort %{Your config/boot.rb is outdated: Run "rake rails:update".} - end + class Base + class << self + def run(&blk) + define_method(:run, &blk) + end - if Rails.vendor_rails? - begin; require "rubygems"; rescue LoadError; return; end + def config=(config) + @@config = config + end - stubs = %w(rails activesupport activerecord actionpack actionmailer activeresource) - stubs.reject! { |s| Gem.loaded_specs.key?(s) } + def config + @@config + end + alias configuration config - stubs.each do |stub| - Gem.loaded_specs[stub] = Gem::Specification.new do |s| - s.name = stub - s.version = Rails::VERSION::STRING - s.loaded_from = "" - end + def gems_dependencies_loaded + config.gems_dependencies_loaded end end - end - - # Set the $LOAD_PATH based on the value of - # Configuration#load_paths. Duplicates are removed. - def set_load_path - load_paths = configuration.load_paths + configuration.framework_paths - load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) } - $LOAD_PATH.uniq! - end - - # Set the paths from which Rails will automatically load source files, and - # the load_once paths. - def set_autoload_paths - require 'active_support/dependencies' - ActiveSupport::Dependencies.load_paths = configuration.load_paths.uniq - ActiveSupport::Dependencies.load_once_paths = configuration.load_once_paths.uniq - 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 + def plugin_loader + @plugin_loader ||= configuration.plugin_loader.new(self) end - # Freeze the arrays so future modifications will fail rather than do nothing mysteriously - configuration.load_once_paths.freeze - end - - # Requires all frameworks specified by the Configuration#frameworks - # list. By default, all frameworks (Active Record, Active Support, - # Action Pack, Action Mailer, and Active Resource) are loaded. - def require_frameworks - require 'active_support/all' - configuration.frameworks.each { |framework| require(framework.to_s) } - rescue LoadError => e - # Re-raise as RuntimeError because Mongrel would swallow LoadError. - raise e.to_s - end - - # Preload all frameworks specified by the Configuration#frameworks. - # Used by Passenger to ensure everything's loaded before forking and - # to avoid autoload race conditions in JRuby. - def preload_frameworks - if configuration.preload_frameworks - configuration.frameworks.each do |framework| - # String#classify and #constantize aren't available yet. - toplevel = Object.const_get(framework.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }) - toplevel.load_all! if toplevel.respond_to?(:load_all!) - end + def gems_dependencies_loaded + self.class.gems_dependencies_loaded end end - # Add the load paths used by support functions such as the info controller - def add_support_load_paths - end - - # Adds all load paths from plugins to the global set of load paths, so that - # code from plugins can be required (explicitly or automatically via ActiveSupport::Dependencies). - def add_plugin_load_paths - require 'active_support/dependencies' - plugin_loader.add_plugin_load_paths - end + class Runner - def add_gem_load_paths - require 'rails/gem_dependency' - Rails::GemDependency.add_frozen_gem_path - unless @configuration.gems.empty? - require "rubygems" - @configuration.gems.each { |gem| gem.add_load_paths } - end - end + attr_reader :names, :initializers + attr_writer :config - def load_gems - unless $gems_rake_task - @configuration.gems.each { |gem| gem.load } + def initialize(parent = nil) + @names = parent ? parent.names.dup : {} + @initializers = parent ? parent.initializers.dup : [] end - end - def check_for_unbuilt_gems - unbuilt_gems = @configuration.gems.select {|gem| gem.frozen? && !gem.built? } - if unbuilt_gems.size > 0 - # don't print if the gems:build rake tasks are being run - unless $gems_build_rake_task - abort <<-end_error -The following gems have native components that need to be built - #{unbuilt_gems.map { |gem| "#{gem.name} #{gem.requirement}" } * "\n "} + def add(name, options = {}, &block) + # If :before or :after is specified, set the index to the right spot + if other = options[:before] || options[:after] + raise Error, "The #{other.inspect} initializer does not exist" unless @names[other] + index = @initializers.index(@names[other]) + index += 1 if options[:after] + end -You're running: - ruby #{Gem.ruby_version} at #{Gem.ruby} - rubygems #{Gem::RubyGemsVersion} at #{Gem.path * ', '} + @initializers.insert(index || -1, block) + @names[name] = block + end -Run `rake gems:build` to build the unbuilt gems. - end_error + def delete(name) + @names[name].tap do |initializer| + @initializers.delete(initializer) + @names.delete(name) end end - end - def check_gem_dependencies - unloaded_gems = @configuration.gems.reject { |g| g.loaded? } - if unloaded_gems.size > 0 - @gems_dependencies_loaded = false - # don't print if the gems rake tasks are being run - unless $gems_rake_task - abort <<-end_error -Missing these required gems: - #{unloaded_gems.map { |gem| "#{gem.name} #{gem.requirement}" } * "\n "} + def run_initializer(initializer) + init_block = initializer.is_a?(Proc) ? initializer : @names[initializer] + container = Class.new(Base, &init_block).new + container.run if container.respond_to?(:run) + end -You're running: - ruby #{Gem.ruby_version} at #{Gem.ruby} - rubygems #{Gem::RubyGemsVersion} at #{Gem.path * ', '} + def run(initializer = nil) + Base.config = @config -Run `rake gems:install` to install the missing gems. - end_error + if initializer + run_initializer(initializer) + else + @initializers.each {|block| run_initializer(block) } end - else - @gems_dependencies_loaded = true end end - # Loads all plugins in config.plugin_paths. plugin_paths - # defaults to vendor/plugins but may also be set to a list of - # paths, such as - # config.plugin_paths = ["#{RAILS_ROOT}/lib/plugins", "#{RAILS_ROOT}/vendor/plugins"] - # - # In the default implementation, as each plugin discovered in plugin_paths is initialized: - # * its +lib+ directory, if present, is added to the load path (immediately after the applications lib directory) - # * init.rb is evaluated, if present - # - # After all plugins are loaded, duplicates are removed from the load path. - # If an array of plugin names is specified in config.plugins, only those plugins will be loaded - # and they plugins will be loaded in that order. Otherwise, plugins are loaded in alphabetical - # order. - # - # if config.plugins ends contains :all then the named plugins will be loaded in the given order and all other - # plugins will be loaded in alphabetical order - def load_plugins - plugin_loader.load_plugins + def self.default + @default ||= Runner.new end - def plugin_loader - @plugin_loader ||= configuration.plugin_loader.new(self) + def self.run(initializer = nil, config = nil) + default.config = config if config + default.run(initializer) end + end - # Loads the environment specified by Configuration#environment_path, which - # is typically one of development, test, or production. - def load_environment - silence_warnings do - return if @environment_loaded - @environment_loaded = true - - config = configuration - constants = self.class.constants + # Check for valid Ruby version (1.8.2 or 1.8.4 or higher). This is done in an + # external file, so we can use it from the `rails` program as well without duplication. + Initializer.default.add :check_ruby_version do + require 'ruby_version_check' + end - eval(IO.read(configuration.environment_path), binding, configuration.environment_path) + Initializer.default.add :set_root_path do + raise 'RAILS_ROOT is not set' unless defined?(RAILS_ROOT) + raise 'RAILS_ROOT is not a directory' unless File.directory?(RAILS_ROOT) - (self.class.constants - constants).each do |const| - Object.const_set(const, self.class.const_get(const)) - end - end - end + configuration.root_path = + # Pathname is incompatible with Windows, but Windows doesn't have + # real symlinks so File.expand_path is safe. + if RUBY_PLATFORM =~ /(:?mswin|mingw)/ + File.expand_path(RAILS_ROOT) - def load_observers - if gems_dependencies_loaded && configuration.frameworks.include?(:active_record) - ActiveRecord::Base.instantiate_observers - end - end - - def load_view_paths - if configuration.frameworks.include?(:action_view) - if configuration.cache_classes - view_path = ActionView::FileSystemResolverWithFallback.new(configuration.view_path) - ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) - ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) - end - end - end - - # Eager load application classes - def load_application_classes - return if $rails_rake_task - if configuration.cache_classes - configuration.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 - - # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the - # multibyte safe operations. Plugin authors supporting other encodings - # should override this behaviour and set the relevant +default_charset+ - # on ActionController::Base. - # - # For Ruby 1.9, UTF-8 is the default internal and external encoding. - def initialize_encoding - if RUBY_VERSION < '1.9' - $KCODE='u' + # Otherwise use Pathname#realpath which respects symlinks. else - Encoding.default_internal = Encoding::UTF_8 - Encoding.default_external = Encoding::UTF_8 + Pathname.new(RAILS_ROOT).realpath.to_s end - end - # This initialization routine does nothing unless :active_record - # is one of the frameworks to load (Configuration#frameworks). If it is, - # this sets the database configuration from Configuration#database_configuration - # and then establishes the connection. - def initialize_database - if configuration.frameworks.include?(:active_record) - ActiveRecord::Base.configurations = configuration.database_configuration - ActiveRecord::Base.establish_connection - end - end + RAILS_ROOT.replace configuration.root_path + end - def initialize_database_middleware - if configuration.frameworks.include?(:active_record) - if configuration.frameworks.include?(:action_controller) && - ActionController::Base.session_store.name == 'ActiveRecord::SessionStore' - configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement - configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache - else - configuration.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement - configuration.middleware.use ActiveRecord::QueryCache - end - end + # If Rails is vendored and RubyGems is available, install stub GemSpecs + # for Rails, Active Support, Active Record, Action Pack, Action Mailer, and + # Active Resource. This allows Gem plugins to depend on Rails even when + # the Gem version of Rails shouldn't be loaded. + Initializer.default.add :install_gem_spec_stubs do + unless Rails.respond_to?(:vendor_rails?) + abort %{Your config/boot.rb is outdated: Run "rake rails:update".} end - def initialize_cache - unless defined?(RAILS_CACHE) - silence_warnings { Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store(configuration.cache_store) } + if Rails.vendor_rails? + begin; require "rubygems"; rescue LoadError; return; end - if RAILS_CACHE.respond_to?(:middleware) - # Insert middleware to setup and teardown local cache for each request - configuration.middleware.insert_after(:"Rack::Lock", RAILS_CACHE.middleware) - end - end - end + stubs = %w(rails activesupport activerecord actionpack actionmailer activeresource) + stubs.reject! { |s| Gem.loaded_specs.key?(s) } - def initialize_framework_caches - if configuration.frameworks.include?(:action_controller) - ActionController::Base.cache_store ||= RAILS_CACHE - end - end - - # If the RAILS_DEFAULT_LOGGER constant is already set, this initialization - # routine does nothing. If the constant is not set, and Configuration#logger - # is not +nil+, this also does nothing. Otherwise, a new logger instance - # is created at Configuration#log_path, with a default log level of - # Configuration#log_level. - # - # If the log could not be created, the log will be set to output to - # +STDERR+, with a log level of +WARN+. - def initialize_logger - # if the environment has explicitly defined a logger, use it - return if Rails.logger - - unless logger = configuration.logger - begin - logger = ActiveSupport::BufferedLogger.new(configuration.log_path) - logger.level = ActiveSupport::BufferedLogger.const_get(configuration.log_level.to_s.upcase) - if configuration.environment == "production" - logger.auto_flushing = false - end - 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 #{configuration.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." - ) + stubs.each do |stub| + Gem.loaded_specs[stub] = Gem::Specification.new do |s| + s.name = stub + s.version = Rails::VERSION::STRING + s.loaded_from = "" end end - - silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger } end + end - # Sets the logger for Active Record, Action Controller, and Action Mailer - # (but only for those frameworks that are to be loaded). If the framework's - # logger is already set, it is not changed, otherwise it is set to use - # RAILS_DEFAULT_LOGGER. - def initialize_framework_logging - for framework in ([ :active_record, :action_controller, :action_mailer ] & configuration.frameworks) - framework.to_s.camelize.constantize.const_get("Base").logger ||= Rails.logger - end + # Set the $LOAD_PATH based on the value of + # Configuration#load_paths. Duplicates are removed. + Initializer.default.add :set_load_path do + load_paths = configuration.load_paths + configuration.framework_paths + load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) } + $LOAD_PATH.uniq! + end - ActiveSupport::Dependencies.logger ||= Rails.logger - Rails.cache.logger ||= Rails.logger + Initializer.default.add :add_gem_load_paths do + require 'rails/gem_dependency' + Rails::GemDependency.add_frozen_gem_path + unless @configuration.gems.empty? + require "rubygems" + @configuration.gems.each { |gem| gem.add_load_paths } end + end - # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ - # (but only for those frameworks that are to be loaded). If the framework's - # paths have already been set, it is not changed, otherwise it is - # set to use Configuration#view_path. - def initialize_framework_views - if configuration.frameworks.include?(:action_view) - view_path = ActionView::PathSet.type_cast(configuration.view_path) - ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) && ActionMailer::Base.view_paths.blank? - ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.blank? - end + # Requires all frameworks specified by the Configuration#frameworks + # list. By default, all frameworks (Active Record, Active Support, + # Action Pack, Action Mailer, and Active Resource) are loaded. + Initializer.default.add :require_frameworks do + begin + require 'active_support/all' + configuration.frameworks.each { |framework| require(framework.to_s) } + rescue LoadError => e + # Re-raise as RuntimeError because Mongrel would swallow LoadError. + raise e.to_s end + end - # If Action Controller is not one of the loaded frameworks (Configuration#frameworks) - # this does nothing. Otherwise, it loads the routing definitions and sets up - # loading module used to lazily load controllers (Configuration#controller_paths). - def initialize_routing - return unless configuration.frameworks.include?(:action_controller) + # Set the paths from which Rails will automatically load source files, and + # the load_once paths. + Initializer.default.add :set_autoload_paths do + require 'active_support/dependencies' + ActiveSupport::Dependencies.load_paths = configuration.load_paths.uniq + ActiveSupport::Dependencies.load_once_paths = configuration.load_once_paths.uniq - ActionController::Routing.controller_paths += configuration.controller_paths - ActionController::Routing::Routes.add_configuration_file(configuration.routes_configuration_file) - ActionController::Routing::Routes.reload! + 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 - # Sets the dependency loading mechanism based on the value of - # Configuration#cache_classes. - def initialize_dependency_mechanism - ActiveSupport::Dependencies.mechanism = configuration.cache_classes ? :require : :load - end + # Freeze the arrays so future modifications will fail rather than do nothing mysteriously + configuration.load_once_paths.freeze + end - # Loads support for "whiny nil" (noisy warnings when methods are invoked - # on +nil+ values) if Configuration#whiny_nils is true. - def initialize_whiny_nils - require('active_support/whiny_nil') if configuration.whiny_nils - end + # Adds all load paths from plugins to the global set of load paths, so that + # code from plugins can be required (explicitly or automatically via ActiveSupport::Dependencies). + Initializer.default.add :add_plugin_load_paths do + require 'active_support/dependencies' + plugin_loader.add_plugin_load_paths + end - # Sets the default value for Time.zone, and turns on ActiveRecord::Base#time_zone_aware_attributes. - # If assigned value cannot be matched to a TimeZone, an exception will be raised. - def initialize_time_zone - if configuration.time_zone - zone_default = Time.__send__(:get_zone, configuration.time_zone) + # Loads the environment specified by Configuration#environment_path, which + # is typically one of development, test, or production. + Initializer.default.add :load_environment do + silence_warnings do + return if @environment_loaded + @environment_loaded = true - unless zone_default - raise \ - 'Value assigned to config.time_zone not recognized.' + - 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.' - end + config = configuration + constants = self.class.constants - Time.zone_default = zone_default + eval(IO.read(configuration.environment_path), binding, configuration.environment_path) - if configuration.frameworks.include?(:active_record) - ActiveRecord::Base.time_zone_aware_attributes = true - ActiveRecord::Base.default_timezone = :utc - end + (self.class.constants - constants).each do |const| + Object.const_set(const, self.class.const_get(const)) end end + end - # Set the i18n configuration from config.i18n but special-case for the load_path which should be - # appended to what's already set instead of overwritten. - def initialize_i18n - configuration.i18n.each do |setting, value| - if setting == :load_path - I18n.load_path += value - else - I18n.send("#{setting}=", value) - end + # Preload all frameworks specified by the Configuration#frameworks. + # Used by Passenger to ensure everything's loaded before forking and + # to avoid autoload race conditions in JRuby. + Initializer.default.add :preload_frameworks do + if configuration.preload_frameworks + configuration.frameworks.each do |framework| + # String#classify and #constantize aren't available yet. + toplevel = Object.const_get(framework.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }) + toplevel.load_all! if toplevel.respond_to?(:load_all!) end end + end - def initialize_metal - Rails::Rack::Metal.requested_metals = configuration.metals - Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths + # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the + # multibyte safe operations. Plugin authors supporting other encodings + # should override this behaviour and set the relevant +default_charset+ + # on ActionController::Base. + # + # For Ruby 1.9, UTF-8 is the default internal and external encoding. + Initializer.default.add :initialize_encoding do + if RUBY_VERSION < '1.9' + $KCODE='u' + else + Encoding.default_internal = Encoding::UTF_8 + Encoding.default_external = Encoding::UTF_8 + end + end - configuration.middleware.insert_before( - :"ActionDispatch::ParamsParser", - Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) + # This initialization routine does nothing unless :active_record + # is one of the frameworks to load (Configuration#frameworks). If it is, + # this sets the database configuration from Configuration#database_configuration + # and then establishes the connection. + Initializer.default.add :initialize_database do + if configuration.frameworks.include?(:active_record) + ActiveRecord::Base.configurations = configuration.database_configuration + ActiveRecord::Base.establish_connection end + end - # Initializes framework-specific settings for each of the loaded frameworks - # (Configuration#frameworks). The available settings map to the accessors - # on each of the corresponding Base classes. - def initialize_framework_settings - configuration.frameworks.each do |framework| - base_class = framework.to_s.camelize.constantize.const_get("Base") + Initializer.default.add :initialize_cache do + unless defined?(RAILS_CACHE) + silence_warnings { Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store(configuration.cache_store) } - configuration.send(framework).each do |setting, value| - base_class.send("#{setting}=", value) - end - end - configuration.active_support.each do |setting, value| - ActiveSupport.send("#{setting}=", value) + if RAILS_CACHE.respond_to?(:middleware) + # Insert middleware to setup and teardown local cache for each request + configuration.middleware.insert_after(:"Rack::Lock", RAILS_CACHE.middleware) end end + end - # Fires the user-supplied after_initialize block (Configuration#after_initialize) - def after_initialize - if gems_dependencies_loaded - configuration.after_initialize_blocks.each do |block| - block.call - end - end + Initializer.default.add :initialize_framework_caches do + if configuration.frameworks.include?(:action_controller) + ActionController::Base.cache_store ||= RAILS_CACHE end + end - def load_application_initializers - if gems_dependencies_loaded - Dir["#{configuration.root_path}/config/initializers/**/*.rb"].sort.each do |initializer| - load(initializer) + Initializer.default.add :initialize_logger do + # if the environment has explicitly defined a logger, use it + next if Rails.logger + + unless logger = configuration.logger + begin + logger = ActiveSupport::BufferedLogger.new(configuration.log_path) + logger.level = ActiveSupport::BufferedLogger.const_get(configuration.log_level.to_s.upcase) + if configuration.environment == "production" + logger.auto_flushing = false end + 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 #{configuration.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." + ) end end - def prepare_dispatcher - return unless configuration.frameworks.include?(:action_controller) - require 'dispatcher' unless defined?(::Dispatcher) - Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) - end - - def disable_dependency_loading - if configuration.cache_classes && !configuration.dependency_loading - ActiveSupport::Dependencies.unhook! - end - end + silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger } end - # The Configuration class holds all the parameters for the Initializer and - # ships with defaults that suites most Rails applications. But it's possible - # to overwrite everything. Usually, you'll create an Configuration file - # implicitly through the block running on the Initializer, but it's also - # possible to create the Configuration instance in advance and pass it in - # like this: - # - # config = Rails::Configuration.new - # Rails::Initializer.run(:process, config) - class Configuration - # The application's base directory. - attr_reader :root_path - - # A stub for setting options on ActionController::Base. - attr_accessor :action_controller - - # A stub for setting options on ActionMailer::Base. - attr_accessor :action_mailer - - # A stub for setting options on ActionView::Base. - attr_accessor :action_view - - # A stub for setting options on ActiveRecord::Base. - attr_accessor :active_record - - # A stub for setting options on ActiveResource::Base. - attr_accessor :active_resource - - # A stub for setting options on ActiveSupport. - attr_accessor :active_support - - # Whether to preload all frameworks at startup. - attr_accessor :preload_frameworks - - # Whether or not classes should be cached (set to false if you want - # application classes to be reloaded on each request) - attr_accessor :cache_classes - - # The list of paths that should be searched for controllers. (Defaults - # to app/controllers.) - attr_accessor :controller_paths - - # The path to the database configuration file to use. (Defaults to - # config/database.yml.) - attr_accessor :database_configuration_file - - # The path to the routes configuration file to use. (Defaults to - # config/routes.rb.) - attr_accessor :routes_configuration_file - - # The list of rails framework components that should be loaded. (Defaults - # to :active_record, :action_controller, - # :action_view, :action_mailer, and - # :active_resource). - attr_accessor :frameworks - - # An array of additional paths to prepend to the load path. By default, - # all +app+, +lib+, +vendor+ and mock paths are included in this list. - attr_accessor :load_paths - - # An array of paths from which Rails will automatically load from only once. - # All elements of this array must also be in +load_paths+. - attr_accessor :load_once_paths - - # An array of paths from which Rails will eager load on boot if cache - # classes is enabled. All elements of this array must also be in - # +load_paths+. - attr_accessor :eager_load_paths - - # The log level to use for the default Rails logger. In production mode, - # this defaults to :info. In development mode, it defaults to - # :debug. - attr_accessor :log_level + # Sets the logger for Active Record, Action Controller, and Action Mailer + # (but only for those frameworks that are to be loaded). If the framework's + # logger is already set, it is not changed, otherwise it is set to use + # RAILS_DEFAULT_LOGGER. + Initializer.default.add :initialize_framework_logging do + for framework in ([ :active_record, :action_controller, :action_mailer ] & configuration.frameworks) + framework.to_s.camelize.constantize.const_get("Base").logger ||= Rails.logger + end - # The path to the log file to use. Defaults to log/#{environment}.log - # (e.g. log/development.log or log/production.log). - attr_accessor :log_path + ActiveSupport::Dependencies.logger ||= Rails.logger + Rails.cache.logger ||= Rails.logger + end - # The specific logger to use. By default, a logger will be created and - # initialized using #log_path and #log_level, but a programmer may - # specifically set the logger to use via this accessor and it will be - # used directly. - attr_accessor :logger + # Sets the dependency loading mechanism based on the value of + # Configuration#cache_classes. + Initializer.default.add :initialize_dependency_mechanism do + ActiveSupport::Dependencies.mechanism = configuration.cache_classes ? :require : :load + end - # The specific cache store to use. By default, the ActiveSupport::Cache::Store will be used. - attr_accessor :cache_store + # Loads support for "whiny nil" (noisy warnings when methods are invoked + # on +nil+ values) if Configuration#whiny_nils is true. + Initializer.default.add :initialize_whiny_nils do + require('active_support/whiny_nil') if configuration.whiny_nils + end - # The root of the application's views. (Defaults to app/views.) - attr_accessor :view_path - # Set to +true+ if you want to be warned (noisily) when you try to invoke - # any method of +nil+. Set to +false+ for the standard Ruby behavior. - attr_accessor :whiny_nils + # Sets the default value for Time.zone, and turns on ActiveRecord::Base#time_zone_aware_attributes. + # If assigned value cannot be matched to a TimeZone, an exception will be raised. + Initializer.default.add :initialize_time_zone do + if configuration.time_zone + zone_default = Time.__send__(:get_zone, configuration.time_zone) - # The list of plugins to load. If this is set to nil, all plugins will - # be loaded. If this is set to [], no plugins will be loaded. Otherwise, - # plugins will be loaded in the order specified. - attr_reader :plugins - def plugins=(plugins) - @plugins = plugins.nil? ? nil : plugins.map { |p| p.to_sym } - end + unless zone_default + raise \ + 'Value assigned to config.time_zone not recognized.' + + 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.' + end - # The list of metals to load. If this is set to nil, all metals will - # be loaded in alphabetical order. If this is set to [], no metals will - # be loaded. Otherwise metals will be loaded in the order specified - attr_accessor :metals - - # The path to the root of the plugins directory. By default, it is in - # vendor/plugins. - attr_accessor :plugin_paths - - # The classes that handle finding the desired plugins that you'd like to load for - # your application. By default it is the Rails::Plugin::FileSystemLocator which finds - # plugins to load in vendor/plugins. You can hook into gem location by subclassing - # Rails::Plugin::Locator and adding it onto the list of plugin_locators. - attr_accessor :plugin_locators - - # The class that handles loading each plugin. Defaults to Rails::Plugin::Loader, but - # a sub class would have access to fine grained modification of the loading behavior. See - # the implementation of Rails::Plugin::Loader for more details. - attr_accessor :plugin_loader - - # Enables or disables plugin reloading. You can get around this setting per plugin. - # If reload_plugins? is false, add this to your plugin's init.rb - # to make it reloadable: - # - # ActiveSupport::Dependencies.load_once_paths.delete lib_path - # - # If reload_plugins? is true, add this to your plugin's init.rb - # to only load it once: - # - # ActiveSupport::Dependencies.load_once_paths << lib_path - # - attr_accessor :reload_plugins - - # Returns true if plugin reloading is enabled. - def reload_plugins? - !!@reload_plugins - end + Time.zone_default = zone_default - # Enables or disables dependency loading during the request cycle. Setting - # dependency_loading to true will allow new classes to be loaded - # during a request. Setting it to false will disable this behavior. - # - # Those who want to run in a threaded environment should disable this - # option and eager load or require all there classes on initialization. - # - # If cache_classes is disabled, dependency loaded will always be - # on. - attr_accessor :dependency_loading - - # An array of gems that this rails application depends on. Rails will automatically load - # these gems during installation, and allow you to install any missing gems with: - # - # rake gems:install - # - # You can add gems with the #gem method. - attr_accessor :gems - - # Adds a single Gem dependency to the rails application. By default, it will require - # the library with the same name as the gem. Use :lib to specify a different name. - # - # # gem 'aws-s3', '>= 0.4.0' - # # require 'aws/s3' - # config.gem 'aws-s3', :lib => 'aws/s3', :version => '>= 0.4.0', \ - # :source => "http://code.whytheluckystiff.net" - # - # To require a library be installed, but not attempt to load it, pass :lib => false - # - # config.gem 'qrp', :version => '0.4.1', :lib => false - def gem(name, options = {}) - @gems << Rails::GemDependency.new(name, options) + if configuration.frameworks.include?(:active_record) + ActiveRecord::Base.time_zone_aware_attributes = true + ActiveRecord::Base.default_timezone = :utc + end end + end - # Deprecated options: - def breakpoint_server(_ = nil) - $stderr.puts %( - ******************************************************************* - * config.breakpoint_server has been deprecated and has no effect. * - ******************************************************************* - ) + # Set the i18n configuration from config.i18n but special-case for the load_path which should be + # appended to what's already set instead of overwritten. + Initializer.default.add :initialize_i18n do + configuration.i18n.each do |setting, value| + if setting == :load_path + I18n.load_path += value + else + I18n.send("#{setting}=", value) + end end - alias_method :breakpoint_server=, :breakpoint_server - - # Sets the default +time_zone+. Setting this will enable +time_zone+ - # awareness for Active Record models and set the Active Record default - # timezone to :utc. - attr_accessor :time_zone + end - # Accessor for i18n settings. - attr_accessor :i18n + # Initializes framework-specific settings for each of the loaded frameworks + # (Configuration#frameworks). The available settings map to the accessors + # on each of the corresponding Base classes. + Initializer.default.add :initialize_framework_settings do + configuration.frameworks.each do |framework| + base_class = framework.to_s.camelize.constantize.const_get("Base") - # Create a new Configuration instance, initialized with the default - # values. - def initialize - set_root_path! - - self.frameworks = default_frameworks - self.load_paths = default_load_paths - self.load_once_paths = default_load_once_paths - self.eager_load_paths = default_eager_load_paths - self.log_path = default_log_path - self.log_level = default_log_level - self.view_path = default_view_path - self.controller_paths = default_controller_paths - self.preload_frameworks = default_preload_frameworks - self.cache_classes = default_cache_classes - self.dependency_loading = default_dependency_loading - self.whiny_nils = default_whiny_nils - self.plugins = default_plugins - self.plugin_paths = default_plugin_paths - self.plugin_locators = default_plugin_locators - self.plugin_loader = default_plugin_loader - self.database_configuration_file = default_database_configuration_file - self.routes_configuration_file = default_routes_configuration_file - self.gems = default_gems - self.i18n = default_i18n - - for framework in default_frameworks - self.send("#{framework}=", Rails::OrderedOptions.new) + configuration.send(framework).each do |setting, value| + base_class.send("#{setting}=", value) end - self.active_support = Rails::OrderedOptions.new end - - # Set the root_path to RAILS_ROOT and canonicalize it. - def set_root_path! - raise 'RAILS_ROOT is not set' unless defined?(::RAILS_ROOT) - raise 'RAILS_ROOT is not a directory' unless File.directory?(::RAILS_ROOT) - - @root_path = - # Pathname is incompatible with Windows, but Windows doesn't have - # real symlinks so File.expand_path is safe. - if RUBY_PLATFORM =~ /(:?mswin|mingw)/ - File.expand_path(::RAILS_ROOT) - - # Otherwise use Pathname#realpath which respects symlinks. - else - Pathname.new(::RAILS_ROOT).realpath.to_s - end - - Object.const_set(:RELATIVE_RAILS_ROOT, ::RAILS_ROOT.dup) unless defined?(::RELATIVE_RAILS_ROOT) - ::RAILS_ROOT.replace @root_path + configuration.active_support.each do |setting, value| + ActiveSupport.send("#{setting}=", value) end + end - # Enable threaded mode. Allows concurrent requests to controller actions and - # multiple database connections. Also disables automatic dependency loading - # after boot, and disables reloading code on every request, as these are - # fundamentally incompatible with thread safety. - def threadsafe! - self.preload_frameworks = true - self.cache_classes = true - self.dependency_loading = false - self.action_controller.allow_concurrency = true - self + # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ + # (but only for those frameworks that are to be loaded). If the framework's + # paths have already been set, it is not changed, otherwise it is + # set to use Configuration#view_path. + Initializer.default.add :initialize_framework_views do + if configuration.frameworks.include?(:action_view) + view_path = ActionView::PathSet.type_cast(configuration.view_path) + ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) && ActionMailer::Base.view_paths.blank? + ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.blank? end + end - # Loads and returns the contents of the #database_configuration_file. The - # contents of the file are processed via ERB before being sent through - # YAML::load. - def database_configuration - require 'erb' - YAML::load(ERB.new(IO.read(database_configuration_file)).result) - end + Initializer.default.add :initialize_metal do + Rails::Rack::Metal.requested_metals = configuration.metals + Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths - # The path to the current environment's file (development.rb, etc.). By - # default the file is at config/environments/#{environment}.rb. - def environment_path - "#{root_path}/config/environments/#{environment}.rb" - end + configuration.middleware.insert_before( + :"ActionDispatch::ParamsParser", + Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) + end - # Return the currently selected environment. By default, it returns the - # value of the RAILS_ENV constant. - def environment - ::RAILS_ENV - end + # Add the load paths used by support functions such as the info controller + Initializer.default.add :add_support_load_paths do + end - # Adds a block which will be executed after rails has been fully initialized. - # Useful for per-environment configuration which depends on the framework being - # fully initialized. - def after_initialize(&after_initialize_block) - after_initialize_blocks << after_initialize_block if after_initialize_block - end + Initializer.default.add :check_for_unbuilt_gems do + unbuilt_gems = @configuration.gems.select {|gem| gem.frozen? && !gem.built? } + if unbuilt_gems.size > 0 + # don't print if the gems:build rake tasks are being run + unless $gems_build_rake_task + abort <<-end_error +The following gems have native components that need to be built +#{unbuilt_gems.map { |gemm| "#{gemm.name} #{gemm.requirement}" } * "\n "} - # Returns the blocks added with Configuration#after_initialize - def after_initialize_blocks - @after_initialize_blocks ||= [] - end +You're running: +ruby #{Gem.ruby_version} at #{Gem.ruby} +rubygems #{Gem::RubyGemsVersion} at #{Gem.path * ', '} - # Add a preparation callback that will run before every request in development - # mode, or before the first request in production. - # - # See Dispatcher#to_prepare. - def to_prepare(&callback) - after_initialize do - require 'dispatcher' unless defined?(::Dispatcher) - Dispatcher.to_prepare(&callback) +Run `rake gems:build` to build the unbuilt gems. + end_error end end + end - def middleware - require 'action_controller' - ActionController::Dispatcher.middleware - end - - def builtin_directories - # Include builtins only in the development environment. - (environment == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : [] + Initializer.default.add :load_gems do + unless $gems_rake_task + @configuration.gems.each { |gem| gem.load } end + end - def framework_paths - paths = %w(railties railties/lib activesupport/lib) - paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) - - [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework| - paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework) - end + # Loads all plugins in config.plugin_paths. plugin_paths + # defaults to vendor/plugins but may also be set to a list of + # paths, such as + # config.plugin_paths = ["#{RAILS_ROOT}/lib/plugins", "#{RAILS_ROOT}/vendor/plugins"] + # + # In the default implementation, as each plugin discovered in plugin_paths is initialized: + # * its +lib+ directory, if present, is added to the load path (immediately after the applications lib directory) + # * init.rb is evaluated, if present + # + # After all plugins are loaded, duplicates are removed from the load path. + # If an array of plugin names is specified in config.plugins, only those plugins will be loaded + # and they plugins will be loaded in that order. Otherwise, plugins are loaded in alphabetical + # order. + # + # if config.plugins ends contains :all then the named plugins will be loaded in the given order and all other + # plugins will be loaded in alphabetical order + Initializer.default.add :load_plugins do + plugin_loader.load_plugins + end - paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + # + # # pick up any gems that plugins depend on + Initializer.default.add :add_gem_load_paths do + require 'rails/gem_dependency' + Rails::GemDependency.add_frozen_gem_path + unless @configuration.gems.empty? + require "rubygems" + @configuration.gems.each { |gem| gem.add_load_paths } end + end - private - def framework_root_path - defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails" - end - - def default_frameworks - [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] - end - - def default_load_paths - paths = [] - - # Add the old mock paths only if the directories exists - paths.concat(Dir["#{root_path}/test/mocks/#{environment}"]) if File.exists?("#{root_path}/test/mocks/#{environment}") - - # Add the app's controller directory - paths.concat(Dir["#{root_path}/app/controllers/"]) - - # Followed by the standard includes. - paths.concat %w( - app - app/metal - app/models - app/controllers - app/helpers - app/services - lib - vendor - ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } - - paths.concat builtin_directories - end - - # Doesn't matter since plugins aren't in load_paths yet. - def default_load_once_paths - [] - end - - def default_eager_load_paths - %w( - app/metal - app/models - app/controllers - app/helpers - ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } - end - - def default_log_path - File.join(root_path, 'log', "#{environment}.log") - end - - def default_log_level - environment == 'production' ? :info : :debug - end - - def default_database_configuration_file - File.join(root_path, 'config', 'database.yml') - end - - def default_routes_configuration_file - File.join(root_path, 'config', 'routes.rb') - end - - def default_view_path - File.join(root_path, 'app', 'views') - end - - def default_controller_paths - paths = [File.join(root_path, 'app', 'controllers')] - paths.concat builtin_directories - paths - end - - def default_dependency_loading - true - end - - def default_preload_frameworks - false - end + # TODO: Figure out if this needs to run a second time + # load_gems - def default_cache_classes - true - end - - def default_whiny_nils - false - end + Initializer.default.add :check_gem_dependencies do + unloaded_gems = @configuration.gems.reject { |g| g.loaded? } + if unloaded_gems.size > 0 + configuration.gems_dependencies_loaded = false + # don't print if the gems rake tasks are being run + unless $gems_rake_task + abort <<-end_error +Missing these required gems: +#{unloaded_gems.map { |gemm| "#{gemm.name} #{gemm.requirement}" } * "\n "} - def default_plugins - nil - end +You're running: +ruby #{Gem.ruby_version} at #{Gem.ruby} +rubygems #{Gem::RubyGemsVersion} at #{Gem.path * ', '} - def default_plugin_paths - ["#{root_path}/vendor/plugins"] +Run `rake gems:install` to install the missing gems. + end_error end + else + configuration.gems_dependencies_loaded = true + end + end - def default_plugin_locators - require 'rails/plugin/locator' - locators = [] - locators << Plugin::GemLocator if defined? Gem - locators << Plugin::FileSystemLocator - end + # # bail out if gems are missing - note that check_gem_dependencies will have + # # already called abort() unless $gems_rake_task is set + # return unless gems_dependencies_loaded - def default_plugin_loader - require 'rails/plugin/loader' - Plugin::Loader + Initializer.default.add :load_application_initializers do + if gems_dependencies_loaded + Dir["#{configuration.root_path}/config/initializers/**/*.rb"].sort.each do |initializer| + load(initializer) end + end + end - def default_cache_store - if File.exist?("#{root_path}/tmp/cache/") - [ :file_store, "#{root_path}/tmp/cache/" ] - else - :memory_store - end + # Fires the user-supplied after_initialize block (Configuration#after_initialize) + Initializer.default.add :after_initialize do + if gems_dependencies_loaded + configuration.after_initialize_blocks.each do |block| + block.call end + end + end - def default_gems - [] + # # Setup database middleware after initializers have run + Initializer.default.add :initialize_database_middleware do + if configuration.frameworks.include?(:active_record) + if configuration.frameworks.include?(:action_controller) && + ActionController::Base.session_store.name == 'ActiveRecord::SessionStore' + configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement + configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache + else + configuration.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement + configuration.middleware.use ActiveRecord::QueryCache end + end + end - def default_i18n - i18n = Rails::OrderedOptions.new - i18n.load_path = [] - if File.exist?(File.join(RAILS_ROOT, 'config', 'locales')) - i18n.load_path << Dir[File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}')] - i18n.load_path.flatten! - end + # # Prepare dispatcher callbacks and run 'prepare' callbacks + Initializer.default.add :prepare_dispatcher do + return unless configuration.frameworks.include?(:action_controller) + require 'dispatcher' unless defined?(::Dispatcher) + Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) + end - i18n - end + # Routing must be initialized after plugins to allow the former to extend the routes + # --- + # If Action Controller is not one of the loaded frameworks (Configuration#frameworks) + # this does nothing. Otherwise, it loads the routing definitions and sets up + # loading module used to lazily load controllers (Configuration#controller_paths). + Initializer.default.add :initialize_routing do + return unless configuration.frameworks.include?(:action_controller) + + ActionController::Routing.controller_paths += configuration.controller_paths + ActionController::Routing::Routes.add_configuration_file(configuration.routes_configuration_file) + ActionController::Routing::Routes.reload! end -end - -# Needs to be duplicated from Active Support since its needed before Active -# Support is available. Here both Options and Hash are namespaced to prevent -# conflicts with other implementations AND with the classes residing in Active Support. -class Rails::OrderedOptions < Array #:nodoc: - def []=(key, value) - key = key.to_sym - - if pair = find_pair(key) - pair.pop - pair << value - else - self << [key, value] + # + # # Observers are loaded after plugins in case Observers or observed models are modified by plugins. + Initializer.default.add :load_observers do + if gems_dependencies_loaded && configuration.frameworks.include?(:active_record) + ActiveRecord::Base.instantiate_observers end end - def [](key) - pair = find_pair(key.to_sym) - pair ? pair.last : nil + # # Load view path cache + Initializer.default.add :load_view_paths do + if configuration.frameworks.include?(:action_view) + if configuration.cache_classes + view_path = ActionView::FileSystemResolverWithFallback.new(configuration.view_path) + ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) + ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) + end + end end - def method_missing(name, *args) - if name.to_s =~ /(.*)=$/ - self[$1.to_sym] = args.first - else - self[name] + # Eager load application classes + Initializer.default.add :load_application_classes do + return if $rails_rake_task + if configuration.cache_classes + configuration.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 find_pair(key) - self.each { |i| return i if i.first == key } - return false + # Disable dependency loading during request cycle + Initializer.default.add :disable_dependency_loading do + if configuration.cache_classes && !configuration.dependency_loading + ActiveSupport::Dependencies.unhook! end -end - + end +end \ No newline at end of file diff --git a/railties/lib/initializer_old.rb b/railties/lib/initializer_old.rb new file mode 100644 index 0000000000..cee5c7bcb6 --- /dev/null +++ b/railties/lib/initializer_old.rb @@ -0,0 +1,1137 @@ +require 'logger' +require 'set' +require 'pathname' + +$LOAD_PATH.unshift File.dirname(__FILE__) +require 'railties_path' +require 'rails/version' +require 'rails/gem_dependency' +require 'rails/rack' + +RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) + +module Rails + class << self + # The Configuration instance used to configure the Rails environment + def configuration + @@configuration + end + + def configuration=(configuration) + @@configuration = configuration + end + + def initialized? + @initialized || false + end + + def initialized=(initialized) + @initialized ||= initialized + end + + def logger + if defined?(RAILS_DEFAULT_LOGGER) + RAILS_DEFAULT_LOGGER + else + nil + end + end + + def backtrace_cleaner + @@backtrace_cleaner ||= begin + # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded + require 'rails/backtrace_cleaner' + Rails::BacktraceCleaner.new + end + end + + def root + Pathname.new(RAILS_ROOT) if defined?(RAILS_ROOT) + end + + def env + @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) + end + + def cache + RAILS_CACHE + end + + def version + VERSION::STRING + end + + def public_path + @@public_path ||= self.root ? File.join(self.root, "public") : "public" + end + + def public_path=(path) + @@public_path = path + end + end + + # The Initializer is responsible for processing the Rails configuration, such + # as setting the $LOAD_PATH, requiring the right frameworks, initializing + # logging, and more. It can be run either as a single command that'll just + # use the default configuration, like this: + # + # Rails::Initializer.run + # + # But normally it's more interesting to pass in a custom configuration + # through the block running: + # + # Rails::Initializer.run do |config| + # config.frameworks -= [ :action_mailer ] + # end + # + # This will use the default configuration options from Rails::Configuration, + # but allow for overwriting on select areas. + class Initializer + # The Configuration instance used by this Initializer instance. + attr_reader :configuration + + # The set of loaded plugins. + attr_reader :loaded_plugins + + # Whether or not all the gem dependencies have been met + attr_reader :gems_dependencies_loaded + + # Runs the initializer. By default, this will invoke the #process method, + # which simply executes all of the initialization routines. Alternately, + # you can specify explicitly which initialization routine you want: + # + # Rails::Initializer.run(:set_load_path) + # + # This is useful if you only want the load path initialized, without + # incurring the overhead of completely loading the entire environment. + def self.run(command = :process, configuration = Configuration.new) + yield configuration if block_given? + initializer = new configuration + initializer.send(command) + initializer + end + + # Create a new Initializer instance that references the given Configuration + # instance. + def initialize(configuration) + @configuration = configuration + @loaded_plugins = [] + end + + # Sequentially step through all of the available initialization routines, + # in order (view execution order in source). + def process + Rails.configuration = configuration + + check_ruby_version + install_gem_spec_stubs + set_load_path + add_gem_load_paths + + require_frameworks + set_autoload_paths + add_plugin_load_paths + load_environment + preload_frameworks + + initialize_encoding + initialize_database + + initialize_cache + initialize_framework_caches + + initialize_logger + initialize_framework_logging + + initialize_dependency_mechanism + initialize_whiny_nils + + initialize_time_zone + initialize_i18n + + initialize_framework_settings + initialize_framework_views + + initialize_metal + + add_support_load_paths + + check_for_unbuilt_gems + + load_gems + load_plugins + + # pick up any gems that plugins depend on + add_gem_load_paths + load_gems + check_gem_dependencies + + # bail out if gems are missing - note that check_gem_dependencies will have + # already called abort() unless $gems_rake_task is set + return unless gems_dependencies_loaded + + load_application_initializers + + # the framework is now fully initialized + after_initialize + + # Setup database middleware after initializers have run + initialize_database_middleware + + # Prepare dispatcher callbacks and run 'prepare' callbacks + prepare_dispatcher + + # Routing must be initialized after plugins to allow the former to extend the routes + initialize_routing + + # Observers are loaded after plugins in case Observers or observed models are modified by plugins. + load_observers + + # Load view path cache + load_view_paths + + # Load application classes + load_application_classes + + # Disable dependency loading during request cycle + disable_dependency_loading + + # Flag initialized + Rails.initialized = true + end + + # Check for valid Ruby version + # This is done in an external file, so we can use it + # from the `rails` program as well without duplication. + def check_ruby_version + require 'ruby_version_check' + end + + # If Rails is vendored and RubyGems is available, install stub GemSpecs + # for Rails, Active Support, Active Record, Action Pack, Action Mailer, and + # Active Resource. This allows Gem plugins to depend on Rails even when + # the Gem version of Rails shouldn't be loaded. + def install_gem_spec_stubs + unless Rails.respond_to?(:vendor_rails?) + abort %{Your config/boot.rb is outdated: Run "rake rails:update".} + end + + if Rails.vendor_rails? + begin; require "rubygems"; rescue LoadError; return; end + + stubs = %w(rails activesupport activerecord actionpack actionmailer activeresource) + stubs.reject! { |s| Gem.loaded_specs.key?(s) } + + stubs.each do |stub| + Gem.loaded_specs[stub] = Gem::Specification.new do |s| + s.name = stub + s.version = Rails::VERSION::STRING + s.loaded_from = "" + end + end + end + end + + # Set the $LOAD_PATH based on the value of + # Configuration#load_paths. Duplicates are removed. + def set_load_path + load_paths = configuration.load_paths + configuration.framework_paths + load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) } + $LOAD_PATH.uniq! + end + + # Set the paths from which Rails will automatically load source files, and + # the load_once paths. + def set_autoload_paths + require 'active_support/dependencies' + ActiveSupport::Dependencies.load_paths = configuration.load_paths.uniq + ActiveSupport::Dependencies.load_once_paths = configuration.load_once_paths.uniq + + 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 + configuration.load_once_paths.freeze + end + + # Requires all frameworks specified by the Configuration#frameworks + # list. By default, all frameworks (Active Record, Active Support, + # Action Pack, Action Mailer, and Active Resource) are loaded. + def require_frameworks + require 'active_support/all' + configuration.frameworks.each { |framework| require(framework.to_s) } + rescue LoadError => e + # Re-raise as RuntimeError because Mongrel would swallow LoadError. + raise e.to_s + end + + # Preload all frameworks specified by the Configuration#frameworks. + # Used by Passenger to ensure everything's loaded before forking and + # to avoid autoload race conditions in JRuby. + def preload_frameworks + if configuration.preload_frameworks + configuration.frameworks.each do |framework| + # String#classify and #constantize aren't available yet. + toplevel = Object.const_get(framework.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }) + toplevel.load_all! if toplevel.respond_to?(:load_all!) + end + end + end + + # Add the load paths used by support functions such as the info controller + def add_support_load_paths + end + + # Adds all load paths from plugins to the global set of load paths, so that + # code from plugins can be required (explicitly or automatically via ActiveSupport::Dependencies). + def add_plugin_load_paths + require 'active_support/dependencies' + plugin_loader.add_plugin_load_paths + end + + def add_gem_load_paths + require 'rails/gem_dependency' + Rails::GemDependency.add_frozen_gem_path + unless @configuration.gems.empty? + require "rubygems" + @configuration.gems.each { |gem| gem.add_load_paths } + end + end + + def load_gems + unless $gems_rake_task + @configuration.gems.each { |gem| gem.load } + end + end + + def check_for_unbuilt_gems + unbuilt_gems = @configuration.gems.select {|gem| gem.frozen? && !gem.built? } + if unbuilt_gems.size > 0 + # don't print if the gems:build rake tasks are being run + unless $gems_build_rake_task + abort <<-end_error +The following gems have native components that need to be built + #{unbuilt_gems.map { |gemm| "#{gemm.name} #{gemm.requirement}" } * "\n "} + +You're running: + ruby #{Gem.ruby_version} at #{Gem.ruby} + rubygems #{Gem::RubyGemsVersion} at #{Gem.path * ', '} + +Run `rake gems:build` to build the unbuilt gems. + end_error + end + end + end + + def check_gem_dependencies + unloaded_gems = @configuration.gems.reject { |g| g.loaded? } + if unloaded_gems.size > 0 + @gems_dependencies_loaded = false + # don't print if the gems rake tasks are being run + unless $gems_rake_task + abort <<-end_error +Missing these required gems: + #{unloaded_gems.map { |gemm| "#{gemm.name} #{gemm.requirement}" } * "\n "} + +You're running: + ruby #{Gem.ruby_version} at #{Gem.ruby} + rubygems #{Gem::RubyGemsVersion} at #{Gem.path * ', '} + +Run `rake gems:install` to install the missing gems. + end_error + end + else + @gems_dependencies_loaded = true + end + end + + # Loads all plugins in config.plugin_paths. plugin_paths + # defaults to vendor/plugins but may also be set to a list of + # paths, such as + # config.plugin_paths = ["#{RAILS_ROOT}/lib/plugins", "#{RAILS_ROOT}/vendor/plugins"] + # + # In the default implementation, as each plugin discovered in plugin_paths is initialized: + # * its +lib+ directory, if present, is added to the load path (immediately after the applications lib directory) + # * init.rb is evaluated, if present + # + # After all plugins are loaded, duplicates are removed from the load path. + # If an array of plugin names is specified in config.plugins, only those plugins will be loaded + # and they plugins will be loaded in that order. Otherwise, plugins are loaded in alphabetical + # order. + # + # if config.plugins ends contains :all then the named plugins will be loaded in the given order and all other + # plugins will be loaded in alphabetical order + def load_plugins + plugin_loader.load_plugins + end + + def plugin_loader + @plugin_loader ||= configuration.plugin_loader.new(self) + end + + # Loads the environment specified by Configuration#environment_path, which + # is typically one of development, test, or production. + def load_environment + silence_warnings do + return if @environment_loaded + @environment_loaded = true + + config = configuration + constants = self.class.constants + + eval(IO.read(configuration.environment_path), binding, configuration.environment_path) + + (self.class.constants - constants).each do |const| + Object.const_set(const, self.class.const_get(const)) + end + end + end + + def load_observers + if gems_dependencies_loaded && configuration.frameworks.include?(:active_record) + ActiveRecord::Base.instantiate_observers + end + end + + def load_view_paths + if configuration.frameworks.include?(:action_view) + if configuration.cache_classes + view_path = ActionView::FileSystemResolverWithFallback.new(configuration.view_path) + ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) + ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) + end + end + end + + # Eager load application classes + def load_application_classes + return if $rails_rake_task + if configuration.cache_classes + configuration.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 + + # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the + # multibyte safe operations. Plugin authors supporting other encodings + # should override this behaviour and set the relevant +default_charset+ + # on ActionController::Base. + # + # For Ruby 1.9, UTF-8 is the default internal and external encoding. + def initialize_encoding + if RUBY_VERSION < '1.9' + $KCODE='u' + else + Encoding.default_internal = Encoding::UTF_8 + Encoding.default_external = Encoding::UTF_8 + end + end + + # This initialization routine does nothing unless :active_record + # is one of the frameworks to load (Configuration#frameworks). If it is, + # this sets the database configuration from Configuration#database_configuration + # and then establishes the connection. + def initialize_database + if configuration.frameworks.include?(:active_record) + ActiveRecord::Base.configurations = configuration.database_configuration + ActiveRecord::Base.establish_connection + end + end + + def initialize_database_middleware + if configuration.frameworks.include?(:active_record) + if configuration.frameworks.include?(:action_controller) && + ActionController::Base.session_store.name == 'ActiveRecord::SessionStore' + configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement + configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache + else + configuration.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement + configuration.middleware.use ActiveRecord::QueryCache + end + end + end + + def initialize_cache + unless defined?(RAILS_CACHE) + silence_warnings { Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store(configuration.cache_store) } + + if RAILS_CACHE.respond_to?(:middleware) + # Insert middleware to setup and teardown local cache for each request + configuration.middleware.insert_after(:"Rack::Lock", RAILS_CACHE.middleware) + end + end + end + + def initialize_framework_caches + if configuration.frameworks.include?(:action_controller) + ActionController::Base.cache_store ||= RAILS_CACHE + end + end + + # If the RAILS_DEFAULT_LOGGER constant is already set, this initialization + # routine does nothing. If the constant is not set, and Configuration#logger + # is not +nil+, this also does nothing. Otherwise, a new logger instance + # is created at Configuration#log_path, with a default log level of + # Configuration#log_level. + # + # If the log could not be created, the log will be set to output to + # +STDERR+, with a log level of +WARN+. + def initialize_logger + # if the environment has explicitly defined a logger, use it + return if Rails.logger + + unless logger = configuration.logger + begin + logger = ActiveSupport::BufferedLogger.new(configuration.log_path) + logger.level = ActiveSupport::BufferedLogger.const_get(configuration.log_level.to_s.upcase) + if configuration.environment == "production" + logger.auto_flushing = false + end + 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 #{configuration.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." + ) + end + end + + silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger } + end + + # Sets the logger for Active Record, Action Controller, and Action Mailer + # (but only for those frameworks that are to be loaded). If the framework's + # logger is already set, it is not changed, otherwise it is set to use + # RAILS_DEFAULT_LOGGER. + def initialize_framework_logging + for framework in ([ :active_record, :action_controller, :action_mailer ] & configuration.frameworks) + framework.to_s.camelize.constantize.const_get("Base").logger ||= Rails.logger + end + + ActiveSupport::Dependencies.logger ||= Rails.logger + Rails.cache.logger ||= Rails.logger + end + + # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ + # (but only for those frameworks that are to be loaded). If the framework's + # paths have already been set, it is not changed, otherwise it is + # set to use Configuration#view_path. + def initialize_framework_views + if configuration.frameworks.include?(:action_view) + view_path = ActionView::PathSet.type_cast(configuration.view_path) + ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) && ActionMailer::Base.view_paths.blank? + ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.blank? + end + end + + # If Action Controller is not one of the loaded frameworks (Configuration#frameworks) + # this does nothing. Otherwise, it loads the routing definitions and sets up + # loading module used to lazily load controllers (Configuration#controller_paths). + def initialize_routing + return unless configuration.frameworks.include?(:action_controller) + + ActionController::Routing.controller_paths += configuration.controller_paths + ActionController::Routing::Routes.add_configuration_file(configuration.routes_configuration_file) + ActionController::Routing::Routes.reload! + end + + # Sets the dependency loading mechanism based on the value of + # Configuration#cache_classes. + def initialize_dependency_mechanism + ActiveSupport::Dependencies.mechanism = configuration.cache_classes ? :require : :load + end + + # Loads support for "whiny nil" (noisy warnings when methods are invoked + # on +nil+ values) if Configuration#whiny_nils is true. + def initialize_whiny_nils + require('active_support/whiny_nil') if configuration.whiny_nils + end + + # Sets the default value for Time.zone, and turns on ActiveRecord::Base#time_zone_aware_attributes. + # If assigned value cannot be matched to a TimeZone, an exception will be raised. + def initialize_time_zone + if configuration.time_zone + zone_default = Time.__send__(:get_zone, configuration.time_zone) + + unless zone_default + raise \ + 'Value assigned to config.time_zone not recognized.' + + 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.' + end + + Time.zone_default = zone_default + + if configuration.frameworks.include?(:active_record) + ActiveRecord::Base.time_zone_aware_attributes = true + ActiveRecord::Base.default_timezone = :utc + end + end + end + + # Set the i18n configuration from config.i18n but special-case for the load_path which should be + # appended to what's already set instead of overwritten. + def initialize_i18n + configuration.i18n.each do |setting, value| + if setting == :load_path + I18n.load_path += value + else + I18n.send("#{setting}=", value) + end + end + end + + def initialize_metal + Rails::Rack::Metal.requested_metals = configuration.metals + Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths + + configuration.middleware.insert_before( + :"ActionDispatch::ParamsParser", + Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) + end + + # Initializes framework-specific settings for each of the loaded frameworks + # (Configuration#frameworks). The available settings map to the accessors + # on each of the corresponding Base classes. + def initialize_framework_settings + configuration.frameworks.each do |framework| + base_class = framework.to_s.camelize.constantize.const_get("Base") + + configuration.send(framework).each do |setting, value| + base_class.send("#{setting}=", value) + end + end + configuration.active_support.each do |setting, value| + ActiveSupport.send("#{setting}=", value) + end + end + + # Fires the user-supplied after_initialize block (Configuration#after_initialize) + def after_initialize + if gems_dependencies_loaded + configuration.after_initialize_blocks.each do |block| + block.call + end + end + end + + def load_application_initializers + if gems_dependencies_loaded + Dir["#{configuration.root_path}/config/initializers/**/*.rb"].sort.each do |initializer| + load(initializer) + end + end + end + + def prepare_dispatcher + return unless configuration.frameworks.include?(:action_controller) + require 'dispatcher' unless defined?(::Dispatcher) + Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) + end + + def disable_dependency_loading + if configuration.cache_classes && !configuration.dependency_loading + ActiveSupport::Dependencies.unhook! + end + end + end + + # The Configuration class holds all the parameters for the Initializer and + # ships with defaults that suites most Rails applications. But it's possible + # to overwrite everything. Usually, you'll create an Configuration file + # implicitly through the block running on the Initializer, but it's also + # possible to create the Configuration instance in advance and pass it in + # like this: + # + # config = Rails::Configuration.new + # Rails::Initializer.run(:process, config) + class Configuration + # The application's base directory. + attr_reader :root_path + + # A stub for setting options on ActionController::Base. + attr_accessor :action_controller + + # A stub for setting options on ActionMailer::Base. + attr_accessor :action_mailer + + # A stub for setting options on ActionView::Base. + attr_accessor :action_view + + # A stub for setting options on ActiveRecord::Base. + attr_accessor :active_record + + # A stub for setting options on ActiveResource::Base. + attr_accessor :active_resource + + # A stub for setting options on ActiveSupport. + attr_accessor :active_support + + # Whether to preload all frameworks at startup. + attr_accessor :preload_frameworks + + # Whether or not classes should be cached (set to false if you want + # application classes to be reloaded on each request) + attr_accessor :cache_classes + + # The list of paths that should be searched for controllers. (Defaults + # to app/controllers.) + attr_accessor :controller_paths + + # The path to the database configuration file to use. (Defaults to + # config/database.yml.) + attr_accessor :database_configuration_file + + # The path to the routes configuration file to use. (Defaults to + # config/routes.rb.) + attr_accessor :routes_configuration_file + + # The list of rails framework components that should be loaded. (Defaults + # to :active_record, :action_controller, + # :action_view, :action_mailer, and + # :active_resource). + attr_accessor :frameworks + + # An array of additional paths to prepend to the load path. By default, + # all +app+, +lib+, +vendor+ and mock paths are included in this list. + attr_accessor :load_paths + + # An array of paths from which Rails will automatically load from only once. + # All elements of this array must also be in +load_paths+. + attr_accessor :load_once_paths + + # An array of paths from which Rails will eager load on boot if cache + # classes is enabled. All elements of this array must also be in + # +load_paths+. + attr_accessor :eager_load_paths + + # The log level to use for the default Rails logger. In production mode, + # this defaults to :info. In development mode, it defaults to + # :debug. + attr_accessor :log_level + + # The path to the log file to use. Defaults to log/#{environment}.log + # (e.g. log/development.log or log/production.log). + attr_accessor :log_path + + # The specific logger to use. By default, a logger will be created and + # initialized using #log_path and #log_level, but a programmer may + # specifically set the logger to use via this accessor and it will be + # used directly. + attr_accessor :logger + + # The specific cache store to use. By default, the ActiveSupport::Cache::Store will be used. + attr_accessor :cache_store + + # The root of the application's views. (Defaults to app/views.) + attr_accessor :view_path + + # Set to +true+ if you want to be warned (noisily) when you try to invoke + # any method of +nil+. Set to +false+ for the standard Ruby behavior. + attr_accessor :whiny_nils + + # The list of plugins to load. If this is set to nil, all plugins will + # be loaded. If this is set to [], no plugins will be loaded. Otherwise, + # plugins will be loaded in the order specified. + attr_reader :plugins + def plugins=(plugins) + @plugins = plugins.nil? ? nil : plugins.map { |p| p.to_sym } + end + + # The list of metals to load. If this is set to nil, all metals will + # be loaded in alphabetical order. If this is set to [], no metals will + # be loaded. Otherwise metals will be loaded in the order specified + attr_accessor :metals + + # The path to the root of the plugins directory. By default, it is in + # vendor/plugins. + attr_accessor :plugin_paths + + # The classes that handle finding the desired plugins that you'd like to load for + # your application. By default it is the Rails::Plugin::FileSystemLocator which finds + # plugins to load in vendor/plugins. You can hook into gem location by subclassing + # Rails::Plugin::Locator and adding it onto the list of plugin_locators. + attr_accessor :plugin_locators + + # The class that handles loading each plugin. Defaults to Rails::Plugin::Loader, but + # a sub class would have access to fine grained modification of the loading behavior. See + # the implementation of Rails::Plugin::Loader for more details. + attr_accessor :plugin_loader + + # Enables or disables plugin reloading. You can get around this setting per plugin. + # If reload_plugins? is false, add this to your plugin's init.rb + # to make it reloadable: + # + # ActiveSupport::Dependencies.load_once_paths.delete lib_path + # + # If reload_plugins? is true, add this to your plugin's init.rb + # to only load it once: + # + # ActiveSupport::Dependencies.load_once_paths << lib_path + # + attr_accessor :reload_plugins + + # Returns true if plugin reloading is enabled. + def reload_plugins? + !!@reload_plugins + end + + # Enables or disables dependency loading during the request cycle. Setting + # dependency_loading to true will allow new classes to be loaded + # during a request. Setting it to false will disable this behavior. + # + # Those who want to run in a threaded environment should disable this + # option and eager load or require all there classes on initialization. + # + # If cache_classes is disabled, dependency loaded will always be + # on. + attr_accessor :dependency_loading + + # An array of gems that this rails application depends on. Rails will automatically load + # these gems during installation, and allow you to install any missing gems with: + # + # rake gems:install + # + # You can add gems with the #gem method. + attr_accessor :gems + + # Adds a single Gem dependency to the rails application. By default, it will require + # the library with the same name as the gem. Use :lib to specify a different name. + # + # # gem 'aws-s3', '>= 0.4.0' + # # require 'aws/s3' + # config.gem 'aws-s3', :lib => 'aws/s3', :version => '>= 0.4.0', \ + # :source => "http://code.whytheluckystiff.net" + # + # To require a library be installed, but not attempt to load it, pass :lib => false + # + # config.gem 'qrp', :version => '0.4.1', :lib => false + def gem(name, options = {}) + @gems << Rails::GemDependency.new(name, options) + end + + # Deprecated options: + def breakpoint_server(_ = nil) + $stderr.puts %( + ******************************************************************* + * config.breakpoint_server has been deprecated and has no effect. * + ******************************************************************* + ) + end + alias_method :breakpoint_server=, :breakpoint_server + + # Sets the default +time_zone+. Setting this will enable +time_zone+ + # awareness for Active Record models and set the Active Record default + # timezone to :utc. + attr_accessor :time_zone + + # Accessor for i18n settings. + attr_accessor :i18n + + # Create a new Configuration instance, initialized with the default + # values. + def initialize + set_root_path! + + self.frameworks = default_frameworks + self.load_paths = default_load_paths + self.load_once_paths = default_load_once_paths + self.eager_load_paths = default_eager_load_paths + self.log_path = default_log_path + self.log_level = default_log_level + self.view_path = default_view_path + self.controller_paths = default_controller_paths + self.preload_frameworks = default_preload_frameworks + self.cache_classes = default_cache_classes + self.dependency_loading = default_dependency_loading + self.whiny_nils = default_whiny_nils + self.plugins = default_plugins + self.plugin_paths = default_plugin_paths + self.plugin_locators = default_plugin_locators + self.plugin_loader = default_plugin_loader + self.database_configuration_file = default_database_configuration_file + self.routes_configuration_file = default_routes_configuration_file + self.gems = default_gems + self.i18n = default_i18n + + for framework in default_frameworks + self.send("#{framework}=", Rails::OrderedOptions.new) + end + self.active_support = Rails::OrderedOptions.new + end + + # Set the root_path to RAILS_ROOT and canonicalize it. + def set_root_path! + raise 'RAILS_ROOT is not set' unless defined?(::RAILS_ROOT) + raise 'RAILS_ROOT is not a directory' unless File.directory?(::RAILS_ROOT) + + @root_path = + # Pathname is incompatible with Windows, but Windows doesn't have + # real symlinks so File.expand_path is safe. + if RUBY_PLATFORM =~ /(:?mswin|mingw)/ + File.expand_path(::RAILS_ROOT) + + # Otherwise use Pathname#realpath which respects symlinks. + else + Pathname.new(::RAILS_ROOT).realpath.to_s + end + + Object.const_set(:RELATIVE_RAILS_ROOT, ::RAILS_ROOT.dup) unless defined?(::RELATIVE_RAILS_ROOT) + ::RAILS_ROOT.replace @root_path + end + + # Enable threaded mode. Allows concurrent requests to controller actions and + # multiple database connections. Also disables automatic dependency loading + # after boot, and disables reloading code on every request, as these are + # fundamentally incompatible with thread safety. + def threadsafe! + self.preload_frameworks = true + self.cache_classes = true + self.dependency_loading = false + self.action_controller.allow_concurrency = true + self + end + + # Loads and returns the contents of the #database_configuration_file. The + # contents of the file are processed via ERB before being sent through + # YAML::load. + def database_configuration + require 'erb' + YAML::load(ERB.new(IO.read(database_configuration_file)).result) + end + + # The path to the current environment's file (development.rb, etc.). By + # default the file is at config/environments/#{environment}.rb. + def environment_path + "#{root_path}/config/environments/#{environment}.rb" + end + + # Return the currently selected environment. By default, it returns the + # value of the RAILS_ENV constant. + def environment + ::RAILS_ENV + end + + # Adds a block which will be executed after rails has been fully initialized. + # Useful for per-environment configuration which depends on the framework being + # fully initialized. + def after_initialize(&after_initialize_block) + after_initialize_blocks << after_initialize_block if after_initialize_block + end + + # Returns the blocks added with Configuration#after_initialize + def after_initialize_blocks + @after_initialize_blocks ||= [] + end + + # Add a preparation callback that will run before every request in development + # mode, or before the first request in production. + # + # See Dispatcher#to_prepare. + def to_prepare(&callback) + after_initialize do + require 'dispatcher' unless defined?(::Dispatcher) + Dispatcher.to_prepare(&callback) + end + end + + def middleware + require 'action_controller' + ActionController::Dispatcher.middleware + end + + def builtin_directories + # Include builtins only in the development environment. + (environment == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : [] + end + + def framework_paths + paths = %w(railties railties/lib activesupport/lib) + paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) + + [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework| + paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework) + end + + paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + end + + private + def framework_root_path + defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails" + end + + def default_frameworks + [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] + end + + def default_load_paths + paths = [] + + # Add the old mock paths only if the directories exists + paths.concat(Dir["#{root_path}/test/mocks/#{environment}"]) if File.exists?("#{root_path}/test/mocks/#{environment}") + + # Add the app's controller directory + paths.concat(Dir["#{root_path}/app/controllers/"]) + + # Followed by the standard includes. + paths.concat %w( + app + app/metal + app/models + app/controllers + app/helpers + app/services + lib + vendor + ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + + paths.concat builtin_directories + end + + # Doesn't matter since plugins aren't in load_paths yet. + def default_load_once_paths + [] + end + + def default_eager_load_paths + %w( + app/metal + app/models + app/controllers + app/helpers + ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + end + + def default_log_path + File.join(root_path, 'log', "#{environment}.log") + end + + def default_log_level + environment == 'production' ? :info : :debug + end + + def default_database_configuration_file + File.join(root_path, 'config', 'database.yml') + end + + def default_routes_configuration_file + File.join(root_path, 'config', 'routes.rb') + end + + def default_view_path + File.join(root_path, 'app', 'views') + end + + def default_controller_paths + paths = [File.join(root_path, 'app', 'controllers')] + paths.concat builtin_directories + paths + end + + def default_dependency_loading + true + end + + def default_preload_frameworks + false + end + + def default_cache_classes + true + end + + def default_whiny_nils + false + end + + def default_plugins + nil + end + + def default_plugin_paths + ["#{root_path}/vendor/plugins"] + end + + def default_plugin_locators + require 'rails/plugin/locator' + locators = [] + locators << Plugin::GemLocator if defined? Gem + locators << Plugin::FileSystemLocator + end + + def default_plugin_loader + require 'rails/plugin/loader' + Plugin::Loader + end + + def default_cache_store + if File.exist?("#{root_path}/tmp/cache/") + [ :file_store, "#{root_path}/tmp/cache/" ] + else + :memory_store + end + end + + def default_gems + [] + end + + def default_i18n + i18n = Rails::OrderedOptions.new + i18n.load_path = [] + + if File.exist?(File.join(RAILS_ROOT, 'config', 'locales')) + i18n.load_path << Dir[File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}')] + i18n.load_path.flatten! + end + + i18n + end + end +end + +# Needs to be duplicated from Active Support since its needed before Active +# Support is available. Here both Options and Hash are namespaced to prevent +# conflicts with other implementations AND with the classes residing in Active Support. +class Rails::OrderedOptions < Array #:nodoc: + def []=(key, value) + key = key.to_sym + + if pair = find_pair(key) + pair.pop + pair << value + else + self << [key, value] + end + end + + def [](key) + pair = find_pair(key.to_sym) + pair ? pair.last : nil + end + + def method_missing(name, *args) + if name.to_s =~ /(.*)=$/ + self[$1.to_sym] = args.first + else + self[name] + end + end + + private + def find_pair(key) + self.each { |i| return i if i.first == key } + return false + end +end + -- cgit v1.2.3 From f2aea4d3eac467b85a63593ba7e2de28b2a2eb0a Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 19 Jun 2009 11:13:38 -0700 Subject: Get initializer_test.rb to pass with the new initializer. --- railties/lib/initializer.rb | 106 ++++++++++++++++++++++++++++++++++-- railties/lib/rails/plugin/loader.rb | 4 +- 2 files changed, 103 insertions(+), 7 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 55fef30dbe..b2dfb6c970 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -2,13 +2,21 @@ module Rails class Configuration attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths, :load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks, - :frameworks, :framework_root_path, :root_path + :frameworks, :framework_root_path, :root_path, :plugin_paths, :plugins, + :plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins, + :i18n def initialize @framework_paths = [] @load_once_paths = [] @after_initialize_blocks = [] @frameworks = [] + @plugin_paths = [] + @loaded_plugins = [] + @plugin_loader = default_plugin_loader + @plugin_locators = default_plugin_locators + @gems = default_gems + @i18n = default_i18n end def after_initialize(&blk) @@ -29,6 +37,44 @@ module Rails def framework_root_path defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails" end + + # TODO: Fix this when there is an application object + def middleware + require 'action_controller' + ActionController::Dispatcher.middleware + end + + def default_plugin_loader + require 'rails/plugin/loader' + Plugin::Loader + end + + def default_plugin_locators + require 'rails/plugin/locator' + locators = [] + locators << Plugin::GemLocator if defined? Gem + locators << Plugin::FileSystemLocator + end + + def default_i18n + i18n = Rails::OrderedOptions.new + i18n.load_path = [] + + if File.exist?(File.join(RAILS_ROOT, 'config', 'locales')) + i18n.load_path << Dir[File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}')] + i18n.load_path.flatten! + end + + i18n + end + + def default_gems + [] + end + + def reload_plugins? + @reload_plugins + end end class Initializer @@ -52,21 +98,26 @@ module Rails def gems_dependencies_loaded config.gems_dependencies_loaded end - end - def plugin_loader - @plugin_loader ||= configuration.plugin_loader.new(self) + def plugin_loader + @plugin_loader ||= configuration.plugin_loader.new(self) + end end def gems_dependencies_loaded self.class.gems_dependencies_loaded end + + def plugin_loader + self.class.plugin_loader + end end class Runner attr_reader :names, :initializers - attr_writer :config + attr_accessor :config + alias configuration config def initialize(parent = nil) @names = parent ? parent.names.dup : {} @@ -596,4 +647,49 @@ Run `rake gems:install` to install the missing gems. ActiveSupport::Dependencies.unhook! end end +end + +# Needs to be duplicated from Active Support since its needed before Active +# Support is available. Here both Options and Hash are namespaced to prevent +# conflicts with other implementations AND with the classes residing in Active Support. +# --- +# TODO: w0t? +module Rails + class << self + def root + Pathname.new(RAILS_ROOT) if defined?(RAILS_ROOT) + end + end + + class OrderedOptions < Array #:nodoc: + def []=(key, value) + key = key.to_sym + + if pair = find_pair(key) + pair.pop + pair << value + else + self << [key, value] + end + end + + def [](key) + pair = find_pair(key.to_sym) + pair ? pair.last : nil + end + + def method_missing(name, *args) + if name.to_s =~ /(.*)=$/ + self[$1.to_sym] = args.first + else + self[name] + end + end + + private + def find_pair(key) + self.each { |i| return i if i.first == key } + return false + end + end end \ No newline at end of file diff --git a/railties/lib/rails/plugin/loader.rb b/railties/lib/rails/plugin/loader.rb index bc22dfc591..7ea9c7c0f3 100644 --- a/railties/lib/rails/plugin/loader.rb +++ b/railties/lib/rails/plugin/loader.rb @@ -105,7 +105,7 @@ module Rails end def register_plugin_as_loaded(plugin) - initializer.loaded_plugins << plugin + initializer.config.loaded_plugins << plugin end def configuration @@ -174,7 +174,7 @@ module Rails end def loaded?(plugin_name) - initializer.loaded_plugins.detect { |plugin| plugin.name == plugin_name.to_s } + initializer.config.loaded_plugins.detect { |plugin| plugin.name == plugin_name.to_s } end def ensure_all_registered_plugins_are_loaded! -- cgit v1.2.3 From 9cfd1d44915f4615bbb760198cd01bf4dfc69f5a Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 19 Jun 2009 11:27:24 -0700 Subject: Get more tests to pass --- railties/lib/initializer.rb | 73 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index b2dfb6c970..3adc3b9ce5 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -1,10 +1,12 @@ +require "pathname" + module Rails class Configuration attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths, :load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks, :frameworks, :framework_root_path, :root_path, :plugin_paths, :plugins, :plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins, - :i18n + :i18n, :gems def initialize @framework_paths = [] @@ -68,6 +70,21 @@ module Rails i18n end + # Adds a single Gem dependency to the rails application. By default, it will require + # the library with the same name as the gem. Use :lib to specify a different name. + # + # # gem 'aws-s3', '>= 0.4.0' + # # require 'aws/s3' + # config.gem 'aws-s3', :lib => 'aws/s3', :version => '>= 0.4.0', \ + # :source => "http://code.whytheluckystiff.net" + # + # To require a library be installed, but not attempt to load it, pass :lib => false + # + # config.gem 'qrp', :version => '0.4.1', :lib => false + def gem(name, options = {}) + @gems << Rails::GemDependency.new(name, options) + end + def default_gems [] end @@ -656,11 +673,63 @@ end # TODO: w0t? module Rails class << self + # The Configuration instance used to configure the Rails environment + def configuration + @@configuration + end + + def configuration=(configuration) + @@configuration = configuration + end + + def initialized? + @initialized || false + end + + def initialized=(initialized) + @initialized ||= initialized + end + + def logger + if defined?(RAILS_DEFAULT_LOGGER) + RAILS_DEFAULT_LOGGER + else + nil + end + end + + def backtrace_cleaner + @@backtrace_cleaner ||= begin + # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded + require 'rails/backtrace_cleaner' + Rails::BacktraceCleaner.new + end + end + def root Pathname.new(RAILS_ROOT) if defined?(RAILS_ROOT) end - end + def env + @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) + end + + def cache + RAILS_CACHE + end + + def version + VERSION::STRING + end + + def public_path + @@public_path ||= self.root ? File.join(self.root, "public") : "public" + end + + def public_path=(path) + @@public_path = path + end + end class OrderedOptions < Array #:nodoc: def []=(key, value) key = key.to_sym -- cgit v1.2.3 From 30baaac5465a352e78dac6330407a7b3460db180 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 19 Jun 2009 11:41:02 -0700 Subject: Fix the default frameworks --- railties/lib/initializer.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 3adc3b9ce5..37bec7a272 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -1,4 +1,8 @@ require "pathname" +require 'railties_path' +require 'rails/version' +require 'rails/gem_dependency' +require 'rails/rack' module Rails class Configuration @@ -12,9 +16,9 @@ module Rails @framework_paths = [] @load_once_paths = [] @after_initialize_blocks = [] - @frameworks = [] @plugin_paths = [] @loaded_plugins = [] + @frameworks = default_frameworks @plugin_loader = default_plugin_loader @plugin_locators = default_plugin_locators @gems = default_gems @@ -46,6 +50,10 @@ module Rails ActionController::Dispatcher.middleware end + def default_frameworks + [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] + end + def default_plugin_loader require 'rails/plugin/loader' Plugin::Loader -- cgit v1.2.3 From 9d398f48275a2740b0c7545da207ac2ebbe012ec Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 19 Jun 2009 12:12:56 -0700 Subject: Got all the railties tests to pass, rails must boot! --- railties/lib/initializer.rb | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 37bec7a272..b64320225b 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -4,6 +4,8 @@ require 'rails/version' require 'rails/gem_dependency' require 'rails/rack' +RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) + module Rails class Configuration attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths, @@ -13,11 +15,13 @@ module Rails :i18n, :gems def initialize + set_root_path! + @framework_paths = [] @load_once_paths = [] @after_initialize_blocks = [] - @plugin_paths = [] @loaded_plugins = [] + @plugin_paths = default_plugin_paths @frameworks = default_frameworks @plugin_loader = default_plugin_loader @plugin_locators = default_plugin_locators @@ -29,6 +33,24 @@ module Rails @after_initialize_blocks << blk if blk end + def set_root_path! + raise 'RAILS_ROOT is not set' unless defined?(RAILS_ROOT) + raise 'RAILS_ROOT is not a directory' unless File.directory?(RAILS_ROOT) + + self.root_path = + # Pathname is incompatible with Windows, but Windows doesn't have + # real symlinks so File.expand_path is safe. + if RUBY_PLATFORM =~ /(:?mswin|mingw)/ + File.expand_path(RAILS_ROOT) + + # Otherwise use Pathname#realpath which respects symlinks. + else + Pathname.new(RAILS_ROOT).realpath.to_s + end + + RAILS_ROOT.replace self.root_path + end + def framework_paths paths = %w(railties railties/lib activesupport/lib) paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) @@ -54,6 +76,10 @@ module Rails [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] end + def default_plugin_paths + ["#{root_path}/vendor/plugins"] + end + def default_plugin_loader require 'rails/plugin/loader' Plugin::Loader -- cgit v1.2.3 From 042bd0a5c8a44c00dfdaa282a81546c0695b172f Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 19 Jun 2009 15:55:32 -0700 Subject: Tests pass, AWDoR passes, and a fresh app boots. --- railties/lib/initializer.rb | 349 +++++++++++++++++++++++++++++--------------- 1 file changed, 228 insertions(+), 121 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index b64320225b..9fe341fd3c 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -1,4 +1,6 @@ require "pathname" + +$LOAD_PATH.unshift File.dirname(__FILE__) require 'railties_path' require 'rails/version' require 'rails/gem_dependency' @@ -7,26 +9,143 @@ require 'rails/rack' RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) module Rails + # Needs to be duplicated from Active Support since its needed before Active + # Support is available. Here both Options and Hash are namespaced to prevent + # conflicts with other implementations AND with the classes residing in Active Support. + # --- + # TODO: w0t? + class << self + # The Configuration instance used to configure the Rails environment + def configuration + @@configuration + end + + def configuration=(configuration) + @@configuration = configuration + end + + def initialized? + @initialized || false + end + + def initialized=(initialized) + @initialized ||= initialized + end + + def logger + if defined?(RAILS_DEFAULT_LOGGER) + RAILS_DEFAULT_LOGGER + else + nil + end + end + + def backtrace_cleaner + @@backtrace_cleaner ||= begin + # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded + require 'rails/backtrace_cleaner' + Rails::BacktraceCleaner.new + end + end + + def root + Pathname.new(RAILS_ROOT) if defined?(RAILS_ROOT) + end + + def env + @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) + end + + def cache + RAILS_CACHE + end + + def version + VERSION::STRING + end + + def public_path + @@public_path ||= self.root ? File.join(self.root, "public") : "public" + end + + def public_path=(path) + @@public_path = path + end + end + + class OrderedOptions < Array #:nodoc: + def []=(key, value) + key = key.to_sym + + if pair = find_pair(key) + pair.pop + pair << value + else + self << [key, value] + end + end + + def [](key) + pair = find_pair(key.to_sym) + pair ? pair.last : nil + end + + def method_missing(name, *args) + if name.to_s =~ /(.*)=$/ + self[$1.to_sym] = args.first + else + self[name] + end + end + + private + def find_pair(key) + self.each { |i| return i if i.first == key } + return false + end + end + class Configuration attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths, :load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks, :frameworks, :framework_root_path, :root_path, :plugin_paths, :plugins, :plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins, - :i18n, :gems + :i18n, :gems, :whiny_nils, :consider_all_requests_local, + :action_controller, :active_record, :action_view, :active_support, + :action_mailer, :active_resource, + :log_path, :log_level, :logger, :preload_frameworks, + :database_configuration_file, :cache_store, :time_zone, + :view_path, :metals, :controller_paths, :routes_configuration_file, + :eager_load_paths, :dependency_loading def initialize set_root_path! - @framework_paths = [] - @load_once_paths = [] - @after_initialize_blocks = [] - @loaded_plugins = [] - @plugin_paths = default_plugin_paths - @frameworks = default_frameworks - @plugin_loader = default_plugin_loader - @plugin_locators = default_plugin_locators - @gems = default_gems - @i18n = default_i18n + @framework_paths = [] + @load_once_paths = [] + @after_initialize_blocks = [] + @loaded_plugins = [] + @dependency_loading = true + @eager_load_paths = default_eager_load_paths + @load_paths = default_load_paths + @plugin_paths = default_plugin_paths + @frameworks = default_frameworks + @plugin_loader = default_plugin_loader + @plugin_locators = default_plugin_locators + @gems = default_gems + @i18n = default_i18n + @log_path = default_log_path + @log_level = default_log_level + @cache_store = default_cache_store + @view_path = default_view_path + @controller_paths = default_controller_paths + @routes_configuration_file = default_routes_configuration_file + @database_configuration_file = default_database_configuration_file + + for framework in default_frameworks + self.send("#{framework}=", Rails::OrderedOptions.new) + end + self.active_support = Rails::OrderedOptions.new end def after_initialize(&blk) @@ -72,6 +191,86 @@ module Rails ActionController::Dispatcher.middleware end + # Loads and returns the contents of the #database_configuration_file. The + # contents of the file are processed via ERB before being sent through + # YAML::load. + def database_configuration + require 'erb' + YAML::load(ERB.new(IO.read(database_configuration_file)).result) + end + + def default_routes_configuration_file + File.join(root_path, 'config', 'routes.rb') + end + + def default_controller_paths + paths = [File.join(root_path, 'app', 'controllers')] + paths.concat builtin_directories + paths + end + + def default_cache_store + if File.exist?("#{root_path}/tmp/cache/") + [ :file_store, "#{root_path}/tmp/cache/" ] + else + :memory_store + end + end + + def default_database_configuration_file + File.join(root_path, 'config', 'database.yml') + end + + def default_view_path + File.join(root_path, 'app', 'views') + end + + def default_eager_load_paths + %w( + app/metal + app/models + app/controllers + app/helpers + ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + end + + def default_load_paths + paths = [] + + # Add the old mock paths only if the directories exists + paths.concat(Dir["#{root_path}/test/mocks/#{RAILS_ENV}"]) if File.exists?("#{root_path}/test/mocks/#{RAILS_ENV}") + + # Add the app's controller directory + paths.concat(Dir["#{root_path}/app/controllers/"]) + + # Followed by the standard includes. + paths.concat %w( + app + app/metal + app/models + app/controllers + app/helpers + app/services + lib + vendor + ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + + paths.concat builtin_directories + end + + def builtin_directories + # Include builtins only in the development environment. + (RAILS_ENV == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : [] + end + + def default_log_path + File.join(root_path, 'log', "#{RAILS_ENV}.log") + end + + def default_log_level + RAILS_ENV == 'production' ? :info : :debug + end + def default_frameworks [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] end @@ -123,6 +322,10 @@ module Rails [] end + def environment_path + "#{root_path}/config/environments/#{RAILS_ENV}.rb" + end + def reload_plugins? @reload_plugins end @@ -201,7 +404,7 @@ module Rails end def run(initializer = nil) - Base.config = @config + Rails.configuration = Base.config = @config if initializer run_initializer(initializer) @@ -217,6 +420,7 @@ module Rails def self.run(initializer = nil, config = nil) default.config = config if config + default.config ||= Configuration.new default.run(initializer) end end @@ -281,9 +485,9 @@ module Rails Initializer.default.add :add_gem_load_paths do require 'rails/gem_dependency' Rails::GemDependency.add_frozen_gem_path - unless @configuration.gems.empty? + unless config.gems.empty? require "rubygems" - @configuration.gems.each { |gem| gem.add_load_paths } + config.gems.each { |gem| gem.add_load_paths } end end @@ -330,7 +534,7 @@ module Rails # is typically one of development, test, or production. Initializer.default.add :load_environment do silence_warnings do - return if @environment_loaded + next if @environment_loaded @environment_loaded = true config = configuration @@ -408,7 +612,7 @@ module Rails begin logger = ActiveSupport::BufferedLogger.new(configuration.log_path) logger.level = ActiveSupport::BufferedLogger.const_get(configuration.log_level.to_s.upcase) - if configuration.environment == "production" + if RAILS_ENV == "production" logger.auto_flushing = false end rescue StandardError => e @@ -525,7 +729,7 @@ module Rails end Initializer.default.add :check_for_unbuilt_gems do - unbuilt_gems = @configuration.gems.select {|gem| gem.frozen? && !gem.built? } + unbuilt_gems = config.gems.select {|gem| gem.frozen? && !gem.built? } if unbuilt_gems.size > 0 # don't print if the gems:build rake tasks are being run unless $gems_build_rake_task @@ -545,7 +749,7 @@ Run `rake gems:build` to build the unbuilt gems. Initializer.default.add :load_gems do unless $gems_rake_task - @configuration.gems.each { |gem| gem.load } + config.gems.each { |gem| gem.load } end end @@ -574,9 +778,9 @@ Run `rake gems:build` to build the unbuilt gems. Initializer.default.add :add_gem_load_paths do require 'rails/gem_dependency' Rails::GemDependency.add_frozen_gem_path - unless @configuration.gems.empty? + unless config.gems.empty? require "rubygems" - @configuration.gems.each { |gem| gem.add_load_paths } + config.gems.each { |gem| gem.add_load_paths } end end @@ -584,7 +788,7 @@ Run `rake gems:build` to build the unbuilt gems. # load_gems Initializer.default.add :check_gem_dependencies do - unloaded_gems = @configuration.gems.reject { |g| g.loaded? } + unloaded_gems = config.gems.reject { |g| g.loaded? } if unloaded_gems.size > 0 configuration.gems_dependencies_loaded = false # don't print if the gems rake tasks are being run @@ -643,7 +847,7 @@ Run `rake gems:install` to install the missing gems. # # Prepare dispatcher callbacks and run 'prepare' callbacks Initializer.default.add :prepare_dispatcher do - return unless configuration.frameworks.include?(:action_controller) + next unless configuration.frameworks.include?(:action_controller) require 'dispatcher' unless defined?(::Dispatcher) Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) end @@ -654,7 +858,7 @@ Run `rake gems:install` to install the missing gems. # this does nothing. Otherwise, it loads the routing definitions and sets up # loading module used to lazily load controllers (Configuration#controller_paths). Initializer.default.add :initialize_routing do - return unless configuration.frameworks.include?(:action_controller) + next unless configuration.frameworks.include?(:action_controller) ActionController::Routing.controller_paths += configuration.controller_paths ActionController::Routing::Routes.add_configuration_file(configuration.routes_configuration_file) @@ -681,7 +885,7 @@ Run `rake gems:install` to install the missing gems. # Eager load application classes Initializer.default.add :load_application_classes do - return if $rails_rake_task + next if $rails_rake_task if configuration.cache_classes configuration.eager_load_paths.each do |load_path| matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/ @@ -699,100 +903,3 @@ Run `rake gems:install` to install the missing gems. end end end - -# Needs to be duplicated from Active Support since its needed before Active -# Support is available. Here both Options and Hash are namespaced to prevent -# conflicts with other implementations AND with the classes residing in Active Support. -# --- -# TODO: w0t? -module Rails - class << self - # The Configuration instance used to configure the Rails environment - def configuration - @@configuration - end - - def configuration=(configuration) - @@configuration = configuration - end - - def initialized? - @initialized || false - end - - def initialized=(initialized) - @initialized ||= initialized - end - - def logger - if defined?(RAILS_DEFAULT_LOGGER) - RAILS_DEFAULT_LOGGER - else - nil - end - end - - def backtrace_cleaner - @@backtrace_cleaner ||= begin - # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded - require 'rails/backtrace_cleaner' - Rails::BacktraceCleaner.new - end - end - - def root - Pathname.new(RAILS_ROOT) if defined?(RAILS_ROOT) - end - - def env - @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) - end - - def cache - RAILS_CACHE - end - - def version - VERSION::STRING - end - - def public_path - @@public_path ||= self.root ? File.join(self.root, "public") : "public" - end - - def public_path=(path) - @@public_path = path - end - end - class OrderedOptions < Array #:nodoc: - def []=(key, value) - key = key.to_sym - - if pair = find_pair(key) - pair.pop - pair << value - else - self << [key, value] - end - end - - def [](key) - pair = find_pair(key.to_sym) - pair ? pair.last : nil - end - - def method_missing(name, *args) - if name.to_s =~ /(.*)=$/ - self[$1.to_sym] = args.first - else - self[name] - end - end - - private - def find_pair(key) - self.each { |i| return i if i.first == key } - return false - end - end -end \ No newline at end of file -- cgit v1.2.3 From ce9d9fda77e6b8ca0ac64e528af1892a5d508636 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Tue, 23 Jun 2009 13:47:16 -0700 Subject: Resurrect threadsafe! --- railties/lib/initializer.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 9fe341fd3c..a4e3747ca4 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -170,6 +170,18 @@ module Rails RAILS_ROOT.replace self.root_path end + # Enable threaded mode. Allows concurrent requests to controller actions and + # multiple database connections. Also disables automatic dependency loading + # after boot, and disables reloading code on every request, as these are + # fundamentally incompatible with thread safety. + def threadsafe! + self.preload_frameworks = true + self.cache_classes = true + self.dependency_loading = false + self.action_controller.allow_concurrency = true + self + end + def framework_paths paths = %w(railties railties/lib activesupport/lib) paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) -- cgit v1.2.3 From 3aad4d7fbec6b0881733d3a9b2aff756f775ad35 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Tue, 23 Jun 2009 16:10:43 -0700 Subject: Separate Rails module methods, the config object, and the initializer into separate files. --- railties/lib/initializer.rb | 336 +----------------------------------- railties/lib/rails/configuration.rb | 239 +++++++++++++++++++++++++ railties/lib/rails/core.rb | 97 +++++++++++ 3 files changed, 338 insertions(+), 334 deletions(-) create mode 100644 railties/lib/rails/configuration.rb create mode 100644 railties/lib/rails/core.rb (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index a4e3747ca4..ef0520d7cc 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -5,344 +5,12 @@ require 'railties_path' require 'rails/version' require 'rails/gem_dependency' require 'rails/rack' +require 'rails/core' +require 'rails/configuration' RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) module Rails - # Needs to be duplicated from Active Support since its needed before Active - # Support is available. Here both Options and Hash are namespaced to prevent - # conflicts with other implementations AND with the classes residing in Active Support. - # --- - # TODO: w0t? - class << self - # The Configuration instance used to configure the Rails environment - def configuration - @@configuration - end - - def configuration=(configuration) - @@configuration = configuration - end - - def initialized? - @initialized || false - end - - def initialized=(initialized) - @initialized ||= initialized - end - - def logger - if defined?(RAILS_DEFAULT_LOGGER) - RAILS_DEFAULT_LOGGER - else - nil - end - end - - def backtrace_cleaner - @@backtrace_cleaner ||= begin - # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded - require 'rails/backtrace_cleaner' - Rails::BacktraceCleaner.new - end - end - - def root - Pathname.new(RAILS_ROOT) if defined?(RAILS_ROOT) - end - - def env - @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) - end - - def cache - RAILS_CACHE - end - - def version - VERSION::STRING - end - - def public_path - @@public_path ||= self.root ? File.join(self.root, "public") : "public" - end - - def public_path=(path) - @@public_path = path - end - end - - class OrderedOptions < Array #:nodoc: - def []=(key, value) - key = key.to_sym - - if pair = find_pair(key) - pair.pop - pair << value - else - self << [key, value] - end - end - - def [](key) - pair = find_pair(key.to_sym) - pair ? pair.last : nil - end - - def method_missing(name, *args) - if name.to_s =~ /(.*)=$/ - self[$1.to_sym] = args.first - else - self[name] - end - end - - private - def find_pair(key) - self.each { |i| return i if i.first == key } - return false - end - end - - class Configuration - attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths, - :load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks, - :frameworks, :framework_root_path, :root_path, :plugin_paths, :plugins, - :plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins, - :i18n, :gems, :whiny_nils, :consider_all_requests_local, - :action_controller, :active_record, :action_view, :active_support, - :action_mailer, :active_resource, - :log_path, :log_level, :logger, :preload_frameworks, - :database_configuration_file, :cache_store, :time_zone, - :view_path, :metals, :controller_paths, :routes_configuration_file, - :eager_load_paths, :dependency_loading - - def initialize - set_root_path! - - @framework_paths = [] - @load_once_paths = [] - @after_initialize_blocks = [] - @loaded_plugins = [] - @dependency_loading = true - @eager_load_paths = default_eager_load_paths - @load_paths = default_load_paths - @plugin_paths = default_plugin_paths - @frameworks = default_frameworks - @plugin_loader = default_plugin_loader - @plugin_locators = default_plugin_locators - @gems = default_gems - @i18n = default_i18n - @log_path = default_log_path - @log_level = default_log_level - @cache_store = default_cache_store - @view_path = default_view_path - @controller_paths = default_controller_paths - @routes_configuration_file = default_routes_configuration_file - @database_configuration_file = default_database_configuration_file - - for framework in default_frameworks - self.send("#{framework}=", Rails::OrderedOptions.new) - end - self.active_support = Rails::OrderedOptions.new - end - - def after_initialize(&blk) - @after_initialize_blocks << blk if blk - end - - def set_root_path! - raise 'RAILS_ROOT is not set' unless defined?(RAILS_ROOT) - raise 'RAILS_ROOT is not a directory' unless File.directory?(RAILS_ROOT) - - self.root_path = - # Pathname is incompatible with Windows, but Windows doesn't have - # real symlinks so File.expand_path is safe. - if RUBY_PLATFORM =~ /(:?mswin|mingw)/ - File.expand_path(RAILS_ROOT) - - # Otherwise use Pathname#realpath which respects symlinks. - else - Pathname.new(RAILS_ROOT).realpath.to_s - end - - RAILS_ROOT.replace self.root_path - end - - # Enable threaded mode. Allows concurrent requests to controller actions and - # multiple database connections. Also disables automatic dependency loading - # after boot, and disables reloading code on every request, as these are - # fundamentally incompatible with thread safety. - def threadsafe! - self.preload_frameworks = true - self.cache_classes = true - self.dependency_loading = false - self.action_controller.allow_concurrency = true - self - end - - def framework_paths - paths = %w(railties railties/lib activesupport/lib) - paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) - - [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework| - paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework) - end - - paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } - end - - def framework_root_path - defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails" - end - - # TODO: Fix this when there is an application object - def middleware - require 'action_controller' - ActionController::Dispatcher.middleware - end - - # Loads and returns the contents of the #database_configuration_file. The - # contents of the file are processed via ERB before being sent through - # YAML::load. - def database_configuration - require 'erb' - YAML::load(ERB.new(IO.read(database_configuration_file)).result) - end - - def default_routes_configuration_file - File.join(root_path, 'config', 'routes.rb') - end - - def default_controller_paths - paths = [File.join(root_path, 'app', 'controllers')] - paths.concat builtin_directories - paths - end - - def default_cache_store - if File.exist?("#{root_path}/tmp/cache/") - [ :file_store, "#{root_path}/tmp/cache/" ] - else - :memory_store - end - end - - def default_database_configuration_file - File.join(root_path, 'config', 'database.yml') - end - - def default_view_path - File.join(root_path, 'app', 'views') - end - - def default_eager_load_paths - %w( - app/metal - app/models - app/controllers - app/helpers - ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } - end - - def default_load_paths - paths = [] - - # Add the old mock paths only if the directories exists - paths.concat(Dir["#{root_path}/test/mocks/#{RAILS_ENV}"]) if File.exists?("#{root_path}/test/mocks/#{RAILS_ENV}") - - # Add the app's controller directory - paths.concat(Dir["#{root_path}/app/controllers/"]) - - # Followed by the standard includes. - paths.concat %w( - app - app/metal - app/models - app/controllers - app/helpers - app/services - lib - vendor - ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } - - paths.concat builtin_directories - end - - def builtin_directories - # Include builtins only in the development environment. - (RAILS_ENV == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : [] - end - - def default_log_path - File.join(root_path, 'log', "#{RAILS_ENV}.log") - end - - def default_log_level - RAILS_ENV == 'production' ? :info : :debug - end - - def default_frameworks - [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] - end - - def default_plugin_paths - ["#{root_path}/vendor/plugins"] - end - - def default_plugin_loader - require 'rails/plugin/loader' - Plugin::Loader - end - - def default_plugin_locators - require 'rails/plugin/locator' - locators = [] - locators << Plugin::GemLocator if defined? Gem - locators << Plugin::FileSystemLocator - end - - def default_i18n - i18n = Rails::OrderedOptions.new - i18n.load_path = [] - - if File.exist?(File.join(RAILS_ROOT, 'config', 'locales')) - i18n.load_path << Dir[File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}')] - i18n.load_path.flatten! - end - - i18n - end - - # Adds a single Gem dependency to the rails application. By default, it will require - # the library with the same name as the gem. Use :lib to specify a different name. - # - # # gem 'aws-s3', '>= 0.4.0' - # # require 'aws/s3' - # config.gem 'aws-s3', :lib => 'aws/s3', :version => '>= 0.4.0', \ - # :source => "http://code.whytheluckystiff.net" - # - # To require a library be installed, but not attempt to load it, pass :lib => false - # - # config.gem 'qrp', :version => '0.4.1', :lib => false - def gem(name, options = {}) - @gems << Rails::GemDependency.new(name, options) - end - - def default_gems - [] - end - - def environment_path - "#{root_path}/config/environments/#{RAILS_ENV}.rb" - end - - def reload_plugins? - @reload_plugins - end - end - class Initializer class Error < StandardError ; end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb new file mode 100644 index 0000000000..c48c989b18 --- /dev/null +++ b/railties/lib/rails/configuration.rb @@ -0,0 +1,239 @@ +module Rails + class Configuration + attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths, + :load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks, + :frameworks, :framework_root_path, :root_path, :plugin_paths, :plugins, + :plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins, + :i18n, :gems, :whiny_nils, :consider_all_requests_local, + :action_controller, :active_record, :action_view, :active_support, + :action_mailer, :active_resource, + :log_path, :log_level, :logger, :preload_frameworks, + :database_configuration_file, :cache_store, :time_zone, + :view_path, :metals, :controller_paths, :routes_configuration_file, + :eager_load_paths, :dependency_loading + + def initialize + set_root_path! + + @framework_paths = [] + @load_once_paths = [] + @after_initialize_blocks = [] + @loaded_plugins = [] + @dependency_loading = true + @eager_load_paths = default_eager_load_paths + @load_paths = default_load_paths + @plugin_paths = default_plugin_paths + @frameworks = default_frameworks + @plugin_loader = default_plugin_loader + @plugin_locators = default_plugin_locators + @gems = default_gems + @i18n = default_i18n + @log_path = default_log_path + @log_level = default_log_level + @cache_store = default_cache_store + @view_path = default_view_path + @controller_paths = default_controller_paths + @routes_configuration_file = default_routes_configuration_file + @database_configuration_file = default_database_configuration_file + + for framework in default_frameworks + self.send("#{framework}=", Rails::OrderedOptions.new) + end + self.active_support = Rails::OrderedOptions.new + end + + def after_initialize(&blk) + @after_initialize_blocks << blk if blk + end + + def set_root_path! + raise 'RAILS_ROOT is not set' unless defined?(RAILS_ROOT) + raise 'RAILS_ROOT is not a directory' unless File.directory?(RAILS_ROOT) + + self.root_path = + # Pathname is incompatible with Windows, but Windows doesn't have + # real symlinks so File.expand_path is safe. + if RUBY_PLATFORM =~ /(:?mswin|mingw)/ + File.expand_path(RAILS_ROOT) + + # Otherwise use Pathname#realpath which respects symlinks. + else + Pathname.new(RAILS_ROOT).realpath.to_s + end + + RAILS_ROOT.replace self.root_path + end + + # Enable threaded mode. Allows concurrent requests to controller actions and + # multiple database connections. Also disables automatic dependency loading + # after boot, and disables reloading code on every request, as these are + # fundamentally incompatible with thread safety. + def threadsafe! + self.preload_frameworks = true + self.cache_classes = true + self.dependency_loading = false + self.action_controller.allow_concurrency = true + self + end + + def framework_paths + paths = %w(railties railties/lib activesupport/lib) + paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) + + [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework| + paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework) + end + + paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + end + + def framework_root_path + defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails" + end + + # TODO: Fix this when there is an application object + def middleware + require 'action_controller' + ActionController::Dispatcher.middleware + end + + # Loads and returns the contents of the #database_configuration_file. The + # contents of the file are processed via ERB before being sent through + # YAML::load. + def database_configuration + require 'erb' + YAML::load(ERB.new(IO.read(database_configuration_file)).result) + end + + def default_routes_configuration_file + File.join(root_path, 'config', 'routes.rb') + end + + def default_controller_paths + paths = [File.join(root_path, 'app', 'controllers')] + paths.concat builtin_directories + paths + end + + def default_cache_store + if File.exist?("#{root_path}/tmp/cache/") + [ :file_store, "#{root_path}/tmp/cache/" ] + else + :memory_store + end + end + + def default_database_configuration_file + File.join(root_path, 'config', 'database.yml') + end + + def default_view_path + File.join(root_path, 'app', 'views') + end + + def default_eager_load_paths + %w( + app/metal + app/models + app/controllers + app/helpers + ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + end + + def default_load_paths + paths = [] + + # Add the old mock paths only if the directories exists + paths.concat(Dir["#{root_path}/test/mocks/#{RAILS_ENV}"]) if File.exists?("#{root_path}/test/mocks/#{RAILS_ENV}") + + # Add the app's controller directory + paths.concat(Dir["#{root_path}/app/controllers/"]) + + # Followed by the standard includes. + paths.concat %w( + app + app/metal + app/models + app/controllers + app/helpers + app/services + lib + vendor + ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } + + paths.concat builtin_directories + end + + def builtin_directories + # Include builtins only in the development environment. + (RAILS_ENV == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : [] + end + + def default_log_path + File.join(root_path, 'log', "#{RAILS_ENV}.log") + end + + def default_log_level + RAILS_ENV == 'production' ? :info : :debug + end + + def default_frameworks + [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] + end + + def default_plugin_paths + ["#{root_path}/vendor/plugins"] + end + + def default_plugin_loader + require 'rails/plugin/loader' + Plugin::Loader + end + + def default_plugin_locators + require 'rails/plugin/locator' + locators = [] + locators << Plugin::GemLocator if defined? Gem + locators << Plugin::FileSystemLocator + end + + def default_i18n + i18n = Rails::OrderedOptions.new + i18n.load_path = [] + + if File.exist?(File.join(RAILS_ROOT, 'config', 'locales')) + i18n.load_path << Dir[File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}')] + i18n.load_path.flatten! + end + + i18n + end + + # Adds a single Gem dependency to the rails application. By default, it will require + # the library with the same name as the gem. Use :lib to specify a different name. + # + # # gem 'aws-s3', '>= 0.4.0' + # # require 'aws/s3' + # config.gem 'aws-s3', :lib => 'aws/s3', :version => '>= 0.4.0', \ + # :source => "http://code.whytheluckystiff.net" + # + # To require a library be installed, but not attempt to load it, pass :lib => false + # + # config.gem 'qrp', :version => '0.4.1', :lib => false + def gem(name, options = {}) + @gems << Rails::GemDependency.new(name, options) + end + + def default_gems + [] + end + + def environment_path + "#{root_path}/config/environments/#{RAILS_ENV}.rb" + end + + def reload_plugins? + @reload_plugins + end + end +end \ No newline at end of file diff --git a/railties/lib/rails/core.rb b/railties/lib/rails/core.rb new file mode 100644 index 0000000000..33695a27b9 --- /dev/null +++ b/railties/lib/rails/core.rb @@ -0,0 +1,97 @@ +module Rails + # Needs to be duplicated from Active Support since its needed before Active + # Support is available. Here both Options and Hash are namespaced to prevent + # conflicts with other implementations AND with the classes residing in Active Support. + # --- + # TODO: w0t? + class << self + # The Configuration instance used to configure the Rails environment + def configuration + @@configuration + end + + def configuration=(configuration) + @@configuration = configuration + end + + def initialized? + @initialized || false + end + + def initialized=(initialized) + @initialized ||= initialized + end + + def logger + if defined?(RAILS_DEFAULT_LOGGER) + RAILS_DEFAULT_LOGGER + else + nil + end + end + + def backtrace_cleaner + @@backtrace_cleaner ||= begin + # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded + require 'rails/backtrace_cleaner' + Rails::BacktraceCleaner.new + end + end + + def root + Pathname.new(RAILS_ROOT) if defined?(RAILS_ROOT) + end + + def env + @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) + end + + def cache + RAILS_CACHE + end + + def version + VERSION::STRING + end + + def public_path + @@public_path ||= self.root ? File.join(self.root, "public") : "public" + end + + def public_path=(path) + @@public_path = path + end + end + + class OrderedOptions < Array #:nodoc: + def []=(key, value) + key = key.to_sym + + if pair = find_pair(key) + pair.pop + pair << value + else + self << [key, value] + end + end + + def [](key) + pair = find_pair(key.to_sym) + pair ? pair.last : nil + end + + def method_missing(name, *args) + if name.to_s =~ /(.*)=$/ + self[$1.to_sym] = args.first + else + self[name] + end + end + + private + def find_pair(key) + self.each { |i| return i if i.first == key } + return false + end + end +end \ No newline at end of file -- cgit v1.2.3 From 92b229e1251d7d3578c3f73e8185972354e76436 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Thu, 25 Jun 2009 17:02:04 +0100 Subject: Make performance tests work again --- railties/lib/performance_test_help.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/performance_test_help.rb b/railties/lib/performance_test_help.rb index 5148b4ab77..2aaa21e85f 100644 --- a/railties/lib/performance_test_help.rb +++ b/railties/lib/performance_test_help.rb @@ -1,4 +1,4 @@ -require 'action_controller/performance_test' +require 'action_controller/testing/performance_test' ActionController::Base.perform_caching = true ActiveSupport::Dependencies.mechanism = :require -- cgit v1.2.3 From c117e8e848f2743bd9b346ccdc0e41e5987699cf Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 25 Jun 2009 14:14:21 -0700 Subject: Run the block passed to #run first when initializing --- railties/lib/initializer.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index ef0520d7cc..68c3576fed 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -101,6 +101,7 @@ module Rails def self.run(initializer = nil, config = nil) default.config = config if config default.config ||= Configuration.new + yield default.config if block_given? default.run(initializer) end end -- cgit v1.2.3 From 8ee60660cec54f008ddaa54a4e8e06d099d8c7f5 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 25 Jun 2009 14:23:03 -0700 Subject: Try speeding up rails booting --- railties/lib/initializer.rb | 16 ++++++++++------ railties/lib/rails/configuration.rb | 1 - 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 68c3576fed..cdf2a22c83 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -177,7 +177,8 @@ module Rails # Action Pack, Action Mailer, and Active Resource) are loaded. Initializer.default.add :require_frameworks do begin - require 'active_support/all' + require 'active_support' + require 'active_support/core_ext/kernel/reporting' configuration.frameworks.each { |framework| require(framework.to_s) } rescue LoadError => e # Re-raise as RuntimeError because Mongrel would swallow LoadError. @@ -397,12 +398,15 @@ module Rails end Initializer.default.add :initialize_metal do - Rails::Rack::Metal.requested_metals = configuration.metals - Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths + # TODO: Make Rails and metal work without ActionController + if defined?(ActionController) + Rails::Rack::Metal.requested_metals = configuration.metals + Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths - configuration.middleware.insert_before( - :"ActionDispatch::ParamsParser", - Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) + configuration.middleware.insert_before( + :"ActionDispatch::ParamsParser", + Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) + end end # Add the load paths used by support functions such as the info controller diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index c48c989b18..fdb071fc18 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -93,7 +93,6 @@ module Rails # TODO: Fix this when there is an application object def middleware - require 'action_controller' ActionController::Dispatcher.middleware end -- cgit v1.2.3 From 2865421f5d77170c1ff39013d9d4efbc98526e74 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 25 Jun 2009 16:18:02 -0700 Subject: Checkpoint. Added a bunch of TODOs and some changes after further going through the initializer --- railties/lib/initializer.rb | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index cdf2a22c83..697ccfa0dc 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -179,6 +179,10 @@ module Rails begin require 'active_support' require 'active_support/core_ext/kernel/reporting' + require 'active_support/core_ext/logger' + + # TODO: This is here to make Sam Ruby's tests pass. Needs discussion. + require 'active_support/core_ext/numeric/bytes' configuration.frameworks.each { |framework| require(framework.to_s) } rescue LoadError => e # Re-raise as RuntimeError because Mongrel would swallow LoadError. @@ -307,6 +311,7 @@ module Rails end end + # TODO: Why are we silencing warning here? silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger } end @@ -326,6 +331,7 @@ module Rails # Sets the dependency loading mechanism based on the value of # Configuration#cache_classes. Initializer.default.add :initialize_dependency_mechanism do + # TODO: Remove files from the $" and always use require ActiveSupport::Dependencies.mechanism = configuration.cache_classes ? :require : :load end @@ -409,10 +415,6 @@ module Rails end end - # Add the load paths used by support functions such as the info controller - Initializer.default.add :add_support_load_paths do - end - Initializer.default.add :check_for_unbuilt_gems do unbuilt_gems = config.gems.select {|gem| gem.frozen? && !gem.built? } if unbuilt_gems.size > 0 @@ -462,6 +464,7 @@ Run `rake gems:build` to build the unbuilt gems. # # pick up any gems that plugins depend on Initializer.default.add :add_gem_load_paths do require 'rails/gem_dependency' + # TODO: This seems extraneous Rails::GemDependency.add_frozen_gem_path unless config.gems.empty? require "rubygems" @@ -529,6 +532,7 @@ Run `rake gems:install` to install the missing gems. end end + # TODO: Make a DSL way to limit an initializer to a particular framework # # Prepare dispatcher callbacks and run 'prepare' callbacks Initializer.default.add :prepare_dispatcher do @@ -557,17 +561,6 @@ Run `rake gems:install` to install the missing gems. end end - # # Load view path cache - Initializer.default.add :load_view_paths do - if configuration.frameworks.include?(:action_view) - if configuration.cache_classes - view_path = ActionView::FileSystemResolverWithFallback.new(configuration.view_path) - ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) - ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) - end - end - end - # Eager load application classes Initializer.default.add :load_application_classes do next if $rails_rake_task -- cgit v1.2.3 From 4153c6b720563e1c43bb96e95f0ff5fbd59d6be7 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 26 Jun 2009 15:36:38 -0700 Subject: Finished a first stab at the Rails application path object. --- railties/lib/rails/paths.rb | 85 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 railties/lib/rails/paths.rb (limited to 'railties/lib') diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb new file mode 100644 index 0000000000..0b43725e32 --- /dev/null +++ b/railties/lib/rails/paths.rb @@ -0,0 +1,85 @@ +require 'set' + +module Rails + class Application + module PathParent + def method_missing(id, *args) + name = id.to_s + + if name =~ /^(.*)=$/ + @children[$1] = Path.new(args.first, @root) + elsif path = @children[name] + path + else + super + end + end + end + + class Root + include PathParent + + attr_reader :path, :load_once, :eager_load + def initialize(path) + raise unless path.is_a?(String) + + @children = {} + + # TODO: Move logic from set_root_path initializer + @path = File.expand_path(path) + @root = self + @load_once, @eager_load = Set.new, Set.new + end + end + + class Path + include PathParent + + attr_reader :path + attr_accessor :glob + + def initialize(path, root) + @children = {} + @root = root + @paths = [path].flatten + @glob = "**/*.rb" + end + + def push(path) + @paths.push path + end + + alias << push + + def unshift(path) + @paths.unshift path + end + + def load_once! + @load_once = true + @root.load_once << self + end + + def load_once? + @load_once + end + + def eager_load! + @eager_load = true + @root.eager_load << self + end + + def eager_load? + @eager_load + end + + def paths + @paths.map do |path| + path.index('/') == 0 ? path : File.join(@root.path, path) + end + end + + alias to_a paths + end + end +end \ No newline at end of file -- cgit v1.2.3 From 188a892c5a097ee6d62249d048a6be7d2dfe9649 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 26 Jun 2009 17:32:05 -0700 Subject: Starting to replace scattered path configuration settings with the path object --- railties/lib/initializer.rb | 27 ++++++----------------- railties/lib/rails/configuration.rb | 33 ++++++++++++++++++++++++++-- railties/lib/rails/paths.rb | 43 +++++++++++++++++++++++++++++++++---- railties/lib/railties_path.rb | 2 +- 4 files changed, 78 insertions(+), 27 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 697ccfa0dc..cd23158e98 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -5,6 +5,7 @@ require 'railties_path' require 'rails/version' require 'rails/gem_dependency' require 'rails/rack' +require 'rails/paths' require 'rails/core' require 'rails/configuration' @@ -112,24 +113,6 @@ module Rails require 'ruby_version_check' end - Initializer.default.add :set_root_path do - raise 'RAILS_ROOT is not set' unless defined?(RAILS_ROOT) - raise 'RAILS_ROOT is not a directory' unless File.directory?(RAILS_ROOT) - - configuration.root_path = - # Pathname is incompatible with Windows, but Windows doesn't have - # real symlinks so File.expand_path is safe. - if RUBY_PLATFORM =~ /(:?mswin|mingw)/ - File.expand_path(RAILS_ROOT) - - # Otherwise use Pathname#realpath which respects symlinks. - else - Pathname.new(RAILS_ROOT).realpath.to_s - end - - RAILS_ROOT.replace configuration.root_path - end - # If Rails is vendored and RubyGems is available, install stub GemSpecs # for Rails, Active Support, Active Record, Action Pack, Action Mailer, and # Active Resource. This allows Gem plugins to depend on Rails even when @@ -158,8 +141,9 @@ module Rails # Set the $LOAD_PATH based on the value of # Configuration#load_paths. Duplicates are removed. Initializer.default.add :set_load_path do - load_paths = configuration.load_paths + configuration.framework_paths - load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) } + # TODO: Think about unifying this with the general Rails paths + configuration.framework_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) } + configuration.paths.add_to_load_path $LOAD_PATH.uniq! end @@ -221,6 +205,8 @@ module Rails Initializer.default.add :load_environment do silence_warnings do next if @environment_loaded + next unless File.file?(configuration.environment_path) + @environment_loaded = true config = configuration @@ -564,6 +550,7 @@ Run `rake gems:install` to install the missing gems. # Eager load application classes Initializer.default.add :load_application_classes do next if $rails_rake_task + if configuration.cache_classes configuration.eager_load_paths.each do |load_path| matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/ diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index fdb071fc18..59132efe98 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -10,7 +10,7 @@ module Rails :log_path, :log_level, :logger, :preload_frameworks, :database_configuration_file, :cache_store, :time_zone, :view_path, :metals, :controller_paths, :routes_configuration_file, - :eager_load_paths, :dependency_loading + :eager_load_paths, :dependency_loading, :paths def initialize set_root_path! @@ -61,7 +61,36 @@ module Rails Pathname.new(RAILS_ROOT).realpath.to_s end - RAILS_ROOT.replace self.root_path + @paths = Rails::Application::Root.new(root_path) + @paths.app = "app" + @paths.app.metals = "app/metal" + @paths.app.models = "app/models" + @paths.app.controllers = "app/controllers" + @paths.app.helpers = "app/helpers" + @paths.app.services = "app/services" + @paths.lib = "lib" + @paths.vendor = "vendor" + @paths.vendor.plugins = "vendor/plugins" + @paths.cache = "tmp/cache" + @paths.config = "config" + @paths.config.locales = "config/locales" + @paths.config.environments = "config/environments" + + @paths.app.controllers.push *builtin_directories + + @paths.app.load_path! + @paths.app.metals.load_path! + @paths.app.models.eager_load! + @paths.app.controllers.eager_load! + @paths.app.helpers.eager_load! + @paths.app.services.load_path! + @paths.app.metals.eager_load! + @paths.lib.load_path! + @paths.vendor.load_path! + + @paths.config.environments.glob = "#{RAILS_ENV}.rb" + + RAILS_ROOT.replace root_path end # Enable threaded mode. Allows concurrent requests to controller actions and diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index 0b43725e32..aada7d4a56 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -19,7 +19,7 @@ module Rails class Root include PathParent - attr_reader :path, :load_once, :eager_load + attr_reader :path def initialize(path) raise unless path.is_a?(String) @@ -28,7 +28,32 @@ module Rails # TODO: Move logic from set_root_path initializer @path = File.expand_path(path) @root = self - @load_once, @eager_load = Set.new, Set.new + @load_once, @eager_load, @all_paths = [], [], [] + end + + def load_once + @load_once.uniq! + @load_once + end + + def eager_load + @eager_load.uniq! + @eager_load + end + + def all_paths + @all_paths.uniq! + @all_paths + end + + def load_paths + all_paths.map { |path| path.paths }.flatten + end + + def add_to_load_path + load_paths.reverse_each do |path| + $LOAD_PATH.unshift(path) if File.directory?(path) + end end end @@ -57,7 +82,7 @@ module Rails def load_once! @load_once = true - @root.load_once << self + @root.load_once.push *self.paths end def load_once? @@ -66,13 +91,23 @@ module Rails def eager_load! @eager_load = true - @root.eager_load << self + @root.all_paths << self + @root.eager_load.push *self.paths end def eager_load? @eager_load end + def load_path! + @load_path = true + @root.all_paths << self + end + + def load_path? + @load_path + end + def paths @paths.map do |path| path.index('/') == 0 ? path : File.join(@root.path, path) diff --git a/railties/lib/railties_path.rb b/railties/lib/railties_path.rb index a298a4cc27..b729c095c8 100644 --- a/railties/lib/railties_path.rb +++ b/railties/lib/railties_path.rb @@ -1 +1 @@ -RAILTIES_PATH = File.join(File.dirname(__FILE__), '..') +RAILTIES_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..')) -- cgit v1.2.3 From f66b5d79c15c92e0712315b5843e611114390a12 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 30 Jun 2009 09:01:46 -0700 Subject: Stop the initializer from blowing up when builtin_directories is empty --- railties/lib/rails/configuration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 59132efe98..7a903211fa 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -76,7 +76,7 @@ module Rails @paths.config.locales = "config/locales" @paths.config.environments = "config/environments" - @paths.app.controllers.push *builtin_directories + builtin_directories.each { |dir| @paths.app.controllers << dir } @paths.app.load_path! @paths.app.metals.load_path! -- cgit v1.2.3 From 9101941c1259627df99c5c13b8e893d5d593265c Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 30 Jun 2009 09:05:53 -0700 Subject: Require core_ext/kernel/requires in test_help to providing #require_library_or_gem --- railties/lib/test_help.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/test_help.rb b/railties/lib/test_help.rb index 94e089a624..ca30bd3187 100644 --- a/railties/lib/test_help.rb +++ b/railties/lib/test_help.rb @@ -3,6 +3,7 @@ silence_warnings { RAILS_ENV = "test" } require 'test/unit' +require 'active_support/core_ext/kernel/requires' require 'action_controller/testing/test_case' require 'action_view/test_case' require 'action_controller/testing/integration' -- cgit v1.2.3 From 132e6d00638dc6370fafa0f1377d3bca17eee2d1 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 30 Jun 2009 13:55:11 -0700 Subject: Add #concat to Rails::Application::Path --- railties/lib/rails/configuration.rb | 2 +- railties/lib/rails/paths.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 7a903211fa..d877915460 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -76,7 +76,7 @@ module Rails @paths.config.locales = "config/locales" @paths.config.environments = "config/environments" - builtin_directories.each { |dir| @paths.app.controllers << dir } + @paths.app.controllers.concat builtin_directories @paths.app.load_path! @paths.app.metals.load_path! diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index aada7d4a56..d2f6d83659 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -80,6 +80,10 @@ module Rails @paths.unshift path end + def concat(paths) + @paths.concat paths + end + def load_once! @load_once = true @root.load_once.push *self.paths -- cgit v1.2.3 From db3de78a83379ab2a58e0d29fb10622b813a4d44 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 30 Jun 2009 14:37:12 -0700 Subject: Bump up the version to 3.0.pre --- railties/lib/rails/version.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb index 99c7516a65..9a65096061 100644 --- a/railties/lib/rails/version.rb +++ b/railties/lib/rails/version.rb @@ -1,8 +1,8 @@ module Rails module VERSION #:nodoc: - MAJOR = 2 - MINOR = 3 - TINY = 2 + MAJOR = 3 + MINOR = 0 + TINY = "pre" STRING = [MAJOR, MINOR, TINY].join('.') end -- cgit v1.2.3 From 9eab435631e1b0a659126d068972ee88cff160de Mon Sep 17 00:00:00 2001 From: "J.D. Hollis" Date: Tue, 30 Jun 2009 08:58:35 -0400 Subject: Only check for built extensions on gem dependencies that are in vendor/gems. [#2825 state:resolved] Signed-off-by: Yehuda Katz + Carl Lerche --- railties/lib/rails/gem_dependency.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/gem_dependency.rb b/railties/lib/rails/gem_dependency.rb index 3cc75494e4..06d830ba24 100644 --- a/railties/lib/rails/gem_dependency.rb +++ b/railties/lib/rails/gem_dependency.rb @@ -122,10 +122,14 @@ module Rails def built? return false unless frozen? - specification.extensions.each do |ext| - makefile = File.join(unpacked_gem_directory, File.dirname(ext), 'Makefile') - return false unless File.exists?(makefile) + + if vendor_gem? + specification.extensions.each do |ext| + makefile = File.join(unpacked_gem_directory, File.dirname(ext), 'Makefile') + return false unless File.exists?(makefile) + end end + true end -- cgit v1.2.3 From 913bb2f4c2feb79dcbc9ed2c0fb1ef6d436f7d02 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 2 Jul 2009 15:47:11 -0700 Subject: Modify the Rails::Application::Path object to allow for more concise path definition. --- railties/lib/rails/paths.rb | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index d2f6d83659..ca56199cbc 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -6,8 +6,8 @@ module Rails def method_missing(id, *args) name = id.to_s - if name =~ /^(.*)=$/ - @children[$1] = Path.new(args.first, @root) + if name =~ /^(.*)=$/ || args.any? + @children[$1 || name] = Path.new(@root, *args) elsif path = @children[name] path else @@ -28,17 +28,15 @@ module Rails # TODO: Move logic from set_root_path initializer @path = File.expand_path(path) @root = self - @load_once, @eager_load, @all_paths = [], [], [] + @all_paths = [] end def load_once - @load_once.uniq! - @load_once + all_paths.map { |path| path.paths if path.load_once? }.compact.flatten.uniq end def eager_load - @eager_load.uniq! - @eager_load + all_paths.map { |path| path.paths if path.eager_load? }.compact.flatten.uniq end def all_paths @@ -47,7 +45,7 @@ module Rails end def load_paths - all_paths.map { |path| path.paths }.flatten + all_paths.map { |path| path.paths if path.load_path? }.compact.flatten.uniq end def add_to_load_path @@ -55,6 +53,14 @@ module Rails $LOAD_PATH.unshift(path) if File.directory?(path) end end + + def push(*) + raise "Application root can only have one physical path" + end + + alias unshift push + alias << push + alias concat push end class Path @@ -63,11 +69,18 @@ module Rails attr_reader :path attr_accessor :glob - def initialize(path, root) + def initialize(root, *paths) + @options = paths.extract_options! @children = {} @root = root - @paths = [path].flatten - @glob = "**/*.rb" + @paths = paths.flatten + @glob = @options[:glob] || "**/*.rb" + + @load_once = @options[:load_once] + @eager_load = @options[:eager_load] + @load_path = @options[:load_path] || @eager_load + + @root.all_paths << self end def push(path) @@ -86,7 +99,6 @@ module Rails def load_once! @load_once = true - @root.load_once.push *self.paths end def load_once? @@ -95,8 +107,7 @@ module Rails def eager_load! @eager_load = true - @root.all_paths << self - @root.eager_load.push *self.paths + @load_path = true end def eager_load? @@ -105,7 +116,6 @@ module Rails def load_path! @load_path = true - @root.all_paths << self end def load_path? -- cgit v1.2.3 From 940aad225af0b963f435a0bf015daece2218d502 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 2 Jul 2009 15:49:35 -0700 Subject: Compact the way application paths are defined --- railties/lib/rails/configuration.rb | 40 ++++++++++++------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index d877915460..1a2f217d20 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -62,33 +62,19 @@ module Rails end @paths = Rails::Application::Root.new(root_path) - @paths.app = "app" - @paths.app.metals = "app/metal" - @paths.app.models = "app/models" - @paths.app.controllers = "app/controllers" - @paths.app.helpers = "app/helpers" - @paths.app.services = "app/services" - @paths.lib = "lib" - @paths.vendor = "vendor" - @paths.vendor.plugins = "vendor/plugins" - @paths.cache = "tmp/cache" - @paths.config = "config" - @paths.config.locales = "config/locales" - @paths.config.environments = "config/environments" - - @paths.app.controllers.concat builtin_directories - - @paths.app.load_path! - @paths.app.metals.load_path! - @paths.app.models.eager_load! - @paths.app.controllers.eager_load! - @paths.app.helpers.eager_load! - @paths.app.services.load_path! - @paths.app.metals.eager_load! - @paths.lib.load_path! - @paths.vendor.load_path! - - @paths.config.environments.glob = "#{RAILS_ENV}.rb" + @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.cache "tmp/cache" + @paths.config "config" + @paths.config.locales "config/locales" + @paths.config.environments "config/environments", :glob => "#{RAILS_ENV}.rb" RAILS_ROOT.replace root_path end -- cgit v1.2.3 From 378a65a909439ebca909125fdfada23ed89cec63 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 2 Jul 2009 17:52:46 -0700 Subject: Added tests for the :install_gem_spec_stubs initializer --- railties/lib/initializer.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index cd23158e98..560105670f 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -125,11 +125,8 @@ module Rails if Rails.vendor_rails? begin; require "rubygems"; rescue LoadError; return; end - stubs = %w(rails activesupport activerecord actionpack actionmailer activeresource) - stubs.reject! { |s| Gem.loaded_specs.key?(s) } - - stubs.each do |stub| - Gem.loaded_specs[stub] = Gem::Specification.new do |s| + %w(rails activesupport activerecord actionpack actionmailer activeresource).each do |stub| + Gem.loaded_specs[stub] ||= Gem::Specification.new do |s| s.name = stub s.version = Rails::VERSION::STRING s.loaded_from = "" -- cgit v1.2.3 From 3c1dab72259d01c6335bf359d7f9b3af69d45bb4 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Fri, 3 Jul 2009 12:23:57 +0100 Subject: Revert "Modify the Rails::Application::Path object to allow for more concise path definition." This reverts commit 913bb2f4c2feb79dcbc9ed2c0fb1ef6d436f7d02. Reason : The server does not start --- railties/lib/rails/paths.rb | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index ca56199cbc..d2f6d83659 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -6,8 +6,8 @@ module Rails def method_missing(id, *args) name = id.to_s - if name =~ /^(.*)=$/ || args.any? - @children[$1 || name] = Path.new(@root, *args) + if name =~ /^(.*)=$/ + @children[$1] = Path.new(args.first, @root) elsif path = @children[name] path else @@ -28,15 +28,17 @@ module Rails # TODO: Move logic from set_root_path initializer @path = File.expand_path(path) @root = self - @all_paths = [] + @load_once, @eager_load, @all_paths = [], [], [] end def load_once - all_paths.map { |path| path.paths if path.load_once? }.compact.flatten.uniq + @load_once.uniq! + @load_once end def eager_load - all_paths.map { |path| path.paths if path.eager_load? }.compact.flatten.uniq + @eager_load.uniq! + @eager_load end def all_paths @@ -45,7 +47,7 @@ module Rails end def load_paths - all_paths.map { |path| path.paths if path.load_path? }.compact.flatten.uniq + all_paths.map { |path| path.paths }.flatten end def add_to_load_path @@ -53,14 +55,6 @@ module Rails $LOAD_PATH.unshift(path) if File.directory?(path) end end - - def push(*) - raise "Application root can only have one physical path" - end - - alias unshift push - alias << push - alias concat push end class Path @@ -69,18 +63,11 @@ module Rails attr_reader :path attr_accessor :glob - def initialize(root, *paths) - @options = paths.extract_options! + def initialize(path, root) @children = {} @root = root - @paths = paths.flatten - @glob = @options[:glob] || "**/*.rb" - - @load_once = @options[:load_once] - @eager_load = @options[:eager_load] - @load_path = @options[:load_path] || @eager_load - - @root.all_paths << self + @paths = [path].flatten + @glob = "**/*.rb" end def push(path) @@ -99,6 +86,7 @@ module Rails def load_once! @load_once = true + @root.load_once.push *self.paths end def load_once? @@ -107,7 +95,8 @@ module Rails def eager_load! @eager_load = true - @load_path = true + @root.all_paths << self + @root.eager_load.push *self.paths end def eager_load? @@ -116,6 +105,7 @@ module Rails def load_path! @load_path = true + @root.all_paths << self end def load_path? -- cgit v1.2.3 From a4bdc00fec623f72592e663e6d7830eea0bc6ea4 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Fri, 3 Jul 2009 12:24:26 +0100 Subject: Revert "Compact the way application paths are defined" This reverts commit 940aad225af0b963f435a0bf015daece2218d502. Reason : The server does not start --- railties/lib/rails/configuration.rb | 40 +++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 1a2f217d20..d877915460 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -62,19 +62,33 @@ module Rails end @paths = Rails::Application::Root.new(root_path) - @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.cache "tmp/cache" - @paths.config "config" - @paths.config.locales "config/locales" - @paths.config.environments "config/environments", :glob => "#{RAILS_ENV}.rb" + @paths.app = "app" + @paths.app.metals = "app/metal" + @paths.app.models = "app/models" + @paths.app.controllers = "app/controllers" + @paths.app.helpers = "app/helpers" + @paths.app.services = "app/services" + @paths.lib = "lib" + @paths.vendor = "vendor" + @paths.vendor.plugins = "vendor/plugins" + @paths.cache = "tmp/cache" + @paths.config = "config" + @paths.config.locales = "config/locales" + @paths.config.environments = "config/environments" + + @paths.app.controllers.concat builtin_directories + + @paths.app.load_path! + @paths.app.metals.load_path! + @paths.app.models.eager_load! + @paths.app.controllers.eager_load! + @paths.app.helpers.eager_load! + @paths.app.services.load_path! + @paths.app.metals.eager_load! + @paths.lib.load_path! + @paths.vendor.load_path! + + @paths.config.environments.glob = "#{RAILS_ENV}.rb" RAILS_ROOT.replace root_path end -- cgit v1.2.3