initializer.rb 31.0 KB
Newer Older
1
require 'logger'
2
require 'set'
3 4 5 6 7 8 9
require 'pathname'

$LOAD_PATH.unshift File.dirname(__FILE__)
require 'railties_path'
require 'rails/version'
require 'rails/plugin/locator'
require 'rails/plugin/loader'
10
require 'rails/gem_dependency'
11
require 'rails/rack'
12

13

14
RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV)
15 16

module Rails
D
David Heinemeier Hansson 已提交
17 18 19 20 21
  class << self
    # The Configuration instance used to configure the Rails environment
    def configuration
      @@configuration
    end
22
  
D
David Heinemeier Hansson 已提交
23 24 25
    def configuration=(configuration)
      @@configuration = configuration
    end
26
  
D
David Heinemeier Hansson 已提交
27 28 29
    def logger
      RAILS_DEFAULT_LOGGER
    end
30
  
D
David Heinemeier Hansson 已提交
31
    def root
32 33 34 35 36
      if defined?(RAILS_ROOT)
        RAILS_ROOT
      else
        nil
      end
D
David Heinemeier Hansson 已提交
37
    end
38
  
D
David Heinemeier Hansson 已提交
39
    def env
40
      StringQuestioneer.new(RAILS_ENV)
D
David Heinemeier Hansson 已提交
41
    end
42
  
D
David Heinemeier Hansson 已提交
43 44 45
    def cache
      RAILS_CACHE
    end
46

47 48 49 50
    def version
      VERSION::STRING
    end

51
    def public_path
52
      @@public_path ||= self.root ? File.join(self.root, "public") : "public"
53 54 55 56 57
    end

    def public_path=(path)
      @@public_path = path
    end
58 59
  end
  
60 61 62 63
  # 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:
64 65 66
  #
  #   Rails::Initializer.run
  #
67 68
  # But normally it's more interesting to pass in a custom configuration
  # through the block running:
69 70
  #
  #   Rails::Initializer.run do |config|
71
  #     config.frameworks -= [ :action_mailer ]
72 73
  #   end
  #
74 75
  # This will use the default configuration options from Rails::Configuration,
  # but allow for overwriting on select areas.
76
  class Initializer
77
    # The Configuration instance used by this Initializer instance.
78
    attr_reader :configuration
79 80 81

    # The set of loaded plugins.
    attr_reader :loaded_plugins
82 83 84 85

    # Whether or not all the gem dependencies have been met
    attr_reader :gems_dependencies_loaded

86 87 88 89 90 91 92
    # 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
93
    # incuring the overhead of completely loading the entire environment.
94 95
    def self.run(command = :process, configuration = Configuration.new)
      yield configuration if block_given?
96 97 98
      initializer = new configuration
      initializer.send(command)
      initializer
99
    end
100

101 102
    # Create a new Initializer instance that references the given Configuration
    # instance.
103 104
    def initialize(configuration)
      @configuration = configuration
105
      @loaded_plugins = []
106
    end
107

108
    # Sequentially step through all of the available initialization routines,
109
    # in order (view execution order in source).
110
    def process
111 112
      Rails.configuration = configuration

113
      check_ruby_version
114
      install_gem_spec_stubs
115
      set_load_path
116
      
117
      require_frameworks
118
      set_autoload_paths
119
      add_gem_load_paths
120
      add_plugin_load_paths
121
      load_environment
122

123
      initialize_encoding
124
      initialize_database
125 126 127 128

      initialize_cache
      initialize_framework_caches

129 130
      initialize_logger
      initialize_framework_logging
131

132
      initialize_framework_views
133 134
      initialize_dependency_mechanism
      initialize_whiny_nils
135
      initialize_temporary_session_directory
136
      initialize_time_zone
137
      initialize_framework_settings
138

139
      add_support_load_paths
J
Jamis Buck 已提交
140

141
      load_gems
J
Jamis Buck 已提交
142
      load_plugins
143 144 145 146

      # pick up any gems that plugins depend on
      add_gem_load_paths
      load_gems
147 148
      check_gem_dependencies
      
149 150
      load_application_initializers

151 152
      # the framework is now fully initialized
      after_initialize
153

154 155 156
      # Prepare dispatcher callbacks and run 'prepare' callbacks
      prepare_dispatcher

157 158 159 160
      # 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.
161
      
162
      load_observers
163
    end
164 165 166 167

    # 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.
168
    def check_ruby_version
169 170 171
      require 'ruby_version_check'
    end

172
    # If Rails is vendored and RubyGems is available, install stub GemSpecs
P
Pratik Naik 已提交
173 174
    # for Rails, Active Support, Active Record, Action Pack, Action Mailer, and
    # Active Resource. This allows Gem plugins to depend on Rails even when
175 176
    # the Gem version of Rails shouldn't be loaded.
    def install_gem_spec_stubs
177
      unless Rails.respond_to?(:vendor_rails?)
P
Pratik Naik 已提交
178
        abort %{Your config/boot.rb is outdated: Run "rake rails:update".}
179 180
      end

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
      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
          end
        end
      end
    end

196 197
    # Set the <tt>$LOAD_PATH</tt> based on the value of
    # Configuration#load_paths. Duplicates are removed.
198
    def set_load_path
199 200
      load_paths = configuration.load_paths + configuration.framework_paths
      load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) }
201 202
      $LOAD_PATH.uniq!
    end
203

204 205
    # Set the paths from which Rails will automatically load source files, and
    # the load_once paths.
206
    def set_autoload_paths
207
      Dependencies.load_paths = configuration.load_paths.uniq
208
      Dependencies.load_once_paths = configuration.load_once_paths.uniq
209

210 211 212
      extra = Dependencies.load_once_paths - Dependencies.load_paths
      unless extra.empty?
        abort <<-end_error
213
          load_once_paths must be a subset of the load_paths.
214 215 216
          Extra items in load_once_paths: #{extra * ','}
        end_error
      end
217

218 219
      # Freeze the arrays so future modifications will fail rather than do nothing mysteriously
      configuration.load_once_paths.freeze
220
    end
221

222
    # Requires all frameworks specified by the Configuration#frameworks
P
Pratik Naik 已提交
223 224
    # list. By default, all frameworks (Active Record, Active Support,
    # Action Pack, Action Mailer, and Active Resource) are loaded.
225 226
    def require_frameworks
      configuration.frameworks.each { |framework| require(framework.to_s) }
227 228 229
    rescue LoadError => e
      # re-raise because Mongrel would swallow it
      raise e.to_s
230
    end
231

232 233
    # Add the load paths used by support functions such as the info controller
    def add_support_load_paths
234
    end
235

236 237 238 239 240 241
    # 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 Dependencies).
    def add_plugin_load_paths
      plugin_loader.add_plugin_load_paths
    end

242 243 244 245 246 247 248 249
    def add_gem_load_paths
      unless @configuration.gems.empty?
        require "rubygems"
        @configuration.gems.each &:add_load_paths
      end
    end

    def load_gems
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
      @configuration.gems.each(&:load)
    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 $rails_gem_installer
          puts %{These gems that this application depends on are missing:}
          unloaded_gems.each do |gem|
            puts " - #{gem.name}"
          end
          puts %{Run "rake gems:install" to install them.}
        end
      else
        @gems_dependencies_loaded = true
      end
268 269
    end

270 271 272
    # Loads all plugins in <tt>config.plugin_paths</tt>.  <tt>plugin_paths</tt>
    # defaults to <tt>vendor/plugins</tt> but may also be set to a list of
    # paths, such as
D
David Heinemeier Hansson 已提交
273
    #   config.plugin_paths = ["#{RAILS_ROOT}/lib/plugins", "#{RAILS_ROOT}/vendor/plugins"]
274
    #
275 276
    # In the default implementation, as each plugin discovered in <tt>plugin_paths</tt> is initialized:
    # * its +lib+ directory, if present, is added to the load path (immediately after the applications lib directory)
277
    # * <tt>init.rb</tt> is evaluated, if present
278 279
    #
    # After all plugins are loaded, duplicates are removed from the load path.
280 281
    # 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
282
    # order.
283 284 285
    #
    # 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
J
Jamis Buck 已提交
286
    def load_plugins
287 288 289 290 291
      plugin_loader.load_plugins
    end

    def plugin_loader
      @plugin_loader ||= configuration.plugin_loader.new(self)
J
Jamis Buck 已提交
292 293
    end

294
    # Loads the environment specified by Configuration#environment_path, which
295
    # is typically one of development, test, or production.
296 297
    def load_environment
      silence_warnings do
298 299 300
        return if @environment_loaded
        @environment_loaded = true
        
301
        config = configuration
302
        constants = self.class.constants
303
        
304
        eval(IO.read(configuration.environment_path), binding, configuration.environment_path)
305
        
306 307 308
        (self.class.constants - constants).each do |const|
          Object.const_set(const, self.class.const_get(const))
        end
309
      end
310
    end
311 312

    def load_observers
313
      if gems_dependencies_loaded && configuration.frameworks.include?(:active_record)
314
        ActiveRecord::Base.instantiate_observers
315
      end
316 317
    end

318 319 320 321 322 323 324
    # 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, this does nothing. Specify the default encoding in the Ruby
    # shebang line if you don't want UTF-8.
325
    def initialize_encoding
326
      $KCODE='u' if RUBY_VERSION < '1.9'
327 328
    end

329 330 331 332
    # This initialization routine does nothing unless <tt>:active_record</tt>
    # 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.
333
    def initialize_database
334 335 336 337
      if configuration.frameworks.include?(:active_record)
        ActiveRecord::Base.configurations = configuration.database_configuration
        ActiveRecord::Base.establish_connection
      end
338
    end
339

340 341 342 343 344 345 346 347 348 349 350 351
    def initialize_cache
      unless defined?(RAILS_CACHE)
        silence_warnings { Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store(configuration.cache_store) }
      end
    end

    def initialize_framework_caches
      if configuration.frameworks.include?(:action_controller)
        ActionController::Base.cache_store ||= RAILS_CACHE
      end
    end

P
Pratik Naik 已提交
352
    # If the RAILS_DEFAULT_LOGGER constant is already set, this initialization
353 354 355 356 357 358 359
    # 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+.
360
    def initialize_logger
361 362 363
      # if the environment has explicitly defined a logger, use it
      return if defined?(RAILS_DEFAULT_LOGGER)

364 365
      unless logger = configuration.logger
        begin
366 367
          logger = ActiveSupport::BufferedLogger.new(configuration.log_path)
          logger.level = ActiveSupport::BufferedLogger.const_get(configuration.log_level.to_s.upcase)
368 369 370 371
          if configuration.environment == "production"
            logger.auto_flushing = false
            logger.set_non_blocking_io
          end
372
        rescue StandardError => e
373 374
          logger = ActiveSupport::BufferedLogger.new(STDERR)
          logger.level = ActiveSupport::BufferedLogger::WARN
375 376 377 378 379
          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
380
      end
381

382
      silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
383
    end
384

P
Pratik Naik 已提交
385
    # Sets the logger for Active Record, Action Controller, and Action Mailer
386 387
    # (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
P
Pratik Naik 已提交
388
    # RAILS_DEFAULT_LOGGER.
389
    def initialize_framework_logging
390 391 392
      for framework in ([ :active_record, :action_controller, :action_mailer ] & configuration.frameworks)
        framework.to_s.camelize.constantize.const_get("Base").logger ||= RAILS_DEFAULT_LOGGER
      end
393 394
      
      RAILS_CACHE.logger ||= RAILS_DEFAULT_LOGGER
395
    end
396

397
    # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+
398
    # (but only for those frameworks that are to be loaded). If the framework's
399
    # paths have already been set, it is not changed, otherwise it is
400
    # set to use Configuration#view_path.
401
    def initialize_framework_views
402 403
      ActionMailer::Base.template_root ||= configuration.view_path  if configuration.frameworks.include?(:action_mailer)
      ActionController::Base.view_paths = [configuration.view_path] if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.empty?
404 405
    end

P
Pratik Naik 已提交
406
    # If Action Controller is not one of the loaded frameworks (Configuration#frameworks)
407 408
    # this does nothing. Otherwise, it loads the routing definitions and sets up
    # loading module used to lazily load controllers (Configuration#controller_paths).
409 410
    def initialize_routing
      return unless configuration.frameworks.include?(:action_controller)
411
      ActionController::Routing.controller_paths = configuration.controller_paths
412
      ActionController::Routing::Routes.configuration_file = configuration.routes_configuration_file
413 414
      ActionController::Routing::Routes.reload
    end
415

416 417
    # Sets the dependency loading mechanism based on the value of
    # Configuration#cache_classes.
418 419
    def initialize_dependency_mechanism
      Dependencies.mechanism = configuration.cache_classes ? :require : :load
420
    end
421

422 423
    # Loads support for "whiny nil" (noisy warnings when methods are invoked
    # on +nil+ values) if Configuration#whiny_nils is true.
424 425 426
    def initialize_whiny_nils
      require('active_support/whiny_nil') if configuration.whiny_nils
    end
427

428
    def initialize_temporary_session_directory
429
      if configuration.frameworks.include?(:action_controller)
430
        session_path = "#{configuration.root_path}/tmp/sessions/"
431 432 433 434
        ActionController::Base.session_options[:tmpdir] = File.exist?(session_path) ? session_path : Dir::tmpdir
      end
    end

P
Pratik Naik 已提交
435
    # Sets the default value for Time.zone, and turns on ActiveRecord::Base#time_zone_aware_attributes.
436
    # If assigned value cannot be matched to a TimeZone, an exception will be raised.
437 438
    def initialize_time_zone
      if configuration.time_zone
439
        zone_default = Time.send!(:get_zone, configuration.time_zone)
440
        unless zone_default
P
Pratik Naik 已提交
441
          raise %{Value assigned to config.time_zone not recognized. Run "rake -D time" for a list of tasks for finding appropriate time zone names.}
442 443
        end
        Time.zone_default = zone_default
444 445 446 447 448 449 450
        if configuration.frameworks.include?(:active_record)
          ActiveRecord::Base.time_zone_aware_attributes = true
          ActiveRecord::Base.default_timezone = :utc
        end
      end
    end

451
    # Initializes framework-specific settings for each of the loaded frameworks
452 453
    # (Configuration#frameworks). The available settings map to the accessors
    # on each of the corresponding Base classes.
454
    def initialize_framework_settings
455 456
      configuration.frameworks.each do |framework|
        base_class = framework.to_s.camelize.constantize.const_get("Base")
457

458 459 460
        configuration.send(framework).each do |setting, value|
          base_class.send("#{setting}=", value)
        end
461
      end
462 463 464
      configuration.active_support.each do |setting, value|
        ActiveSupport.send("#{setting}=", value)
      end
465
    end
466 467

    # Fires the user-supplied after_initialize block (Configuration#after_initialize)
468
    def after_initialize
469
      if gems_dependencies_loaded
470 471 472
        configuration.after_initialize_blocks.each do |block|
          block.call
        end
473
      end
474
    end
475

476
    def load_application_initializers
477
      if gems_dependencies_loaded
478 479 480
        Dir["#{configuration.root_path}/config/initializers/**/*.rb"].sort.each do |initializer|
          load(initializer)
        end
481 482
      end
    end
483

484 485 486 487 488 489
    def prepare_dispatcher
      require 'dispatcher' unless defined?(::Dispatcher)
      Dispatcher.define_dispatcher_callbacks(configuration.cache_classes)
      Dispatcher.new(RAILS_DEFAULT_LOGGER).send :run_callbacks, :prepare_dispatch
    end

490
  end
491

492 493 494 495 496 497
  # 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:
498 499 500
  #
  #   config = Rails::Configuration.new
  #   Rails::Initializer.run(:process, config)
501
  class Configuration
502 503 504
    # The application's base directory.
    attr_reader :root_path

P
Pratik Naik 已提交
505
    # A stub for setting options on ActionController::Base.
506
    attr_accessor :action_controller
507

P
Pratik Naik 已提交
508
    # A stub for setting options on ActionMailer::Base.
509
    attr_accessor :action_mailer
510

P
Pratik Naik 已提交
511
    # A stub for setting options on ActionView::Base.
512
    attr_accessor :action_view
513

P
Pratik Naik 已提交
514
    # A stub for setting options on ActiveRecord::Base.
515
    attr_accessor :active_record
516

P
Pratik Naik 已提交
517
    # A stub for setting options on ActiveRecord::Base.
518 519
    attr_accessor :active_resource

P
Pratik Naik 已提交
520
    # A stub for setting options on ActiveSupport.
521 522
    attr_accessor :active_support

523 524 525
    # 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
526

527 528 529 530 531 532 533
    # The list of paths that should be searched for controllers. (Defaults
    # to <tt>app/controllers</tt> and <tt>components</tt>.)
    attr_accessor :controller_paths

    # The path to the database configuration file to use. (Defaults to
    # <tt>config/database.yml</tt>.)
    attr_accessor :database_configuration_file
534 535 536 537
    
    # The path to the routes configuration file to use. (Defaults to
    # <tt>config/routes.rb</tt>.)
    attr_accessor :routes_configuration_file
538

539 540 541
    # The list of rails framework components that should be loaded. (Defaults
    # to <tt>:active_record</tt>, <tt>:action_controller</tt>,
    # <tt>:action_view</tt>, <tt>:action_mailer</tt>, and
D
David Heinemeier Hansson 已提交
542
    # <tt>:active_resource</tt>).
543
    attr_accessor :frameworks
544

545 546 547
    # 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
548

549
    # An array of paths from which Rails will automatically load from only once.
550
    # All elements of this array must also be in +load_paths+.
551
    attr_accessor :load_once_paths
552

553 554 555 556
    # The log level to use for the default Rails logger. In production mode,
    # this defaults to <tt>:info</tt>. In development mode, it defaults to
    # <tt>:debug</tt>.
    attr_accessor :log_level
557

558 559 560
    # 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
561

562 563 564 565 566
    # 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
567

568 569 570
    # The specific cache store to use. By default, the ActiveSupport::Cache::Store will be used.
    attr_accessor :cache_store

571 572
    # The root of the application's views. (Defaults to <tt>app/views</tt>.)
    attr_accessor :view_path
573

574 575 576
    # 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
577

578 579 580
    # The list of plugins to load. If this is set to <tt>nil</tt>, all plugins will
    # be loaded. If this is set to <tt>[]</tt>, no plugins will be loaded. Otherwise,
    # plugins will be loaded in the order specified.
581 582 583 584
    attr_reader :plugins
    def plugins=(plugins)
      @plugins = plugins.nil? ? nil : plugins.map { |p| p.to_sym }
    end
585

586 587 588
    # The path to the root of the plugins directory. By default, it is in
    # <tt>vendor/plugins</tt>.
    attr_accessor :plugin_paths
589

590 591 592 593 594
    # 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 <tt>vendor/plugins</tt>. You can hook into gem location by subclassing
    # Rails::Plugin::Locator and adding it onto the list of <tt>plugin_locators</tt>.
    attr_accessor :plugin_locators
595 596

    # The class that handles loading each plugin. Defaults to Rails::Plugin::Loader, but
597 598 599
    # 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
600 601
    
    # Enables or disables plugin reloading.  You can get around this setting per plugin.
P
Pratik Naik 已提交
602 603
    # If <tt>reload_plugins?</tt> is false, add this to your plugin's <tt>init.rb</tt>
    # to make it reloadable:
604 605 606
    #
    #   Dependencies.load_once_paths.delete lib_path
    #
P
Pratik Naik 已提交
607 608
    # If <tt>reload_plugins?</tt> is true, add this to your plugin's <tt>init.rb</tt>
    # to only load it once:
609 610 611 612 613 614 615 616 617
    #
    #   Dependencies.load_once_paths << lib_path
    #
    attr_accessor :reload_plugins

    # Returns true if plugin reloading is enabled.
    def reload_plugins?
      !!@reload_plugins
    end
618 619 620 621 622 623

    # 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
    #
R
Rick Olson 已提交
624
    # You can add gems with the #gem method.
625 626 627 628 629 630 631 632 633 634 635 636
    attr_accessor :gems

    # Adds a single Gem dependency to the rails application.
    #
    #   # 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"
    #
    def gem(name, options = {})
      @gems << Rails::GemDependency.new(name, options)
    end
637 638 639 640 641 642 643 644 645 646
    
    # 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
647

P
Pratik Naik 已提交
648 649 650
    # Sets the default +time_zone+.  Setting this will enable +time_zone+
    # awareness for Active Record models and set the Active Record default
    # timezone to <tt>:utc</tt>.
651 652
    attr_accessor :time_zone

653 654
    # Create a new Configuration instance, initialized with the default
    # values.
655
    def initialize
656 657
      set_root_path!

658 659
      self.frameworks                   = default_frameworks
      self.load_paths                   = default_load_paths
660
      self.load_once_paths              = default_load_once_paths
661 662 663 664 665 666
      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.cache_classes                = default_cache_classes
      self.whiny_nils                   = default_whiny_nils
667
      self.plugins                      = default_plugins
668
      self.plugin_paths                 = default_plugin_paths
669
      self.plugin_locators              = default_plugin_locators
670
      self.plugin_loader                = default_plugin_loader
671
      self.database_configuration_file  = default_database_configuration_file
672
      self.routes_configuration_file    = default_routes_configuration_file
673
      self.gems                         = default_gems
674

675
      for framework in default_frameworks
676
        self.send("#{framework}=", Rails::OrderedOptions.new)
677
      end
678
      self.active_support = Rails::OrderedOptions.new
679
    end
680

681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
    # 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
696 697
      
      Object.const_set(:RELATIVE_RAILS_ROOT, ::RAILS_ROOT.dup) unless defined?(::RELATIVE_RAILS_ROOT)
698
      ::RAILS_ROOT.replace @root_path
699 700
    end

701 702 703
    # 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.
704
    def database_configuration
705
      YAML::load(ERB.new(IO.read(database_configuration_file)).result)
706
    end
707

P
Pratik Naik 已提交
708
    # The path to the current environment's file (<tt>development.rb</tt>, etc.). By
709
    # default the file is at <tt>config/environments/#{environment}.rb</tt>.
710
    def environment_path
711
      "#{root_path}/config/environments/#{environment}.rb"
712
    end
J
Jamis Buck 已提交
713

714
    # Return the currently selected environment. By default, it returns the
P
Pratik Naik 已提交
715
    # value of the RAILS_ENV constant.
716 717 718
    def environment
      ::RAILS_ENV
    end
719

720
    # Adds a block which will be executed after rails has been fully initialized.
721
    # Useful for per-environment configuration which depends on the framework being
722 723
    # fully initialized.
    def after_initialize(&after_initialize_block)
724
      after_initialize_blocks << after_initialize_block if after_initialize_block
725
    end
726

727 728 729
    # Returns the blocks added with Configuration#after_initialize
    def after_initialize_blocks
      @after_initialize_blocks ||= []
730
    end
731

N
Nicholas Seckar 已提交
732 733
    # Add a preparation callback that will run before every request in development
    # mode, or before the first request in production.
734
    #
N
Nicholas Seckar 已提交
735 736
    # See Dispatcher#to_prepare.
    def to_prepare(&callback)
737 738 739 740
      after_initialize do 
        require 'dispatcher' unless defined?(::Dispatcher)
        Dispatcher.to_prepare(&callback)
      end
N
Nicholas Seckar 已提交
741
    end
742

743 744 745 746
    def builtin_directories
      # Include builtins only in the development environment.
      (environment == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : []
    end
747

748
    def framework_paths
749 750 751 752 753 754 755 756
      paths = %w(railties railties/lib activesupport/lib)
      paths << 'actionpack/lib' if frameworks.include? :action_controller or 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) }
757
    end
758

759
    private
760 761 762 763
      def framework_root_path
        defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails"
      end

764
      def default_frameworks
765
        [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ]
766
      end
767

768
      def default_load_paths
769 770 771 772
        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}")
773

N
Nicholas Seckar 已提交
774 775
        # Add the app's controller directory
        paths.concat(Dir["#{root_path}/app/controllers/"])
776

777
        # Then components subdirectories.
778
        paths.concat(Dir["#{root_path}/components/[_a-z]*"])
779 780 781

        # Followed by the standard includes.
        paths.concat %w(
782 783
          app
          app/models
784 785 786
          app/controllers
          app/helpers
          app/services
787 788 789 790
          components
          config
          lib
          vendor
791
        ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
792

793
        paths.concat builtin_directories
794
      end
795

796
      # Doesn't matter since plugins aren't in load_paths yet.
797
      def default_load_once_paths
798
        []
799
      end
800 801

      def default_log_path
802
        File.join(root_path, 'log', "#{environment}.log")
803
      end
804

805
      def default_log_level
806
        environment == 'production' ? :info : :debug
807
      end
808

809
      def default_database_configuration_file
810
        File.join(root_path, 'config', 'database.yml')
811
      end
812

813 814 815 816
      def default_routes_configuration_file
        File.join(root_path, 'config', 'routes.rb')
      end

817
      def default_view_path
818
        File.join(root_path, 'app', 'views')
819
      end
820

821
      def default_controller_paths
822
        paths = [File.join(root_path, 'app', 'controllers')]
823 824
        paths.concat builtin_directories
        paths
825
      end
826

827 828 829
      def default_dependency_mechanism
        :load
      end
830

831 832 833
      def default_cache_classes
        false
      end
834

835 836 837
      def default_whiny_nils
        false
      end
838

839
      def default_plugins
840
        nil
841 842
      end

843 844 845
      def default_plugin_paths
        ["#{root_path}/vendor/plugins"]
      end
846

847
      def default_plugin_locators
848 849 850
        locators = []
        locators << Plugin::GemLocator if defined? Gem
        locators << Plugin::FileSystemLocator
851
      end
852

853 854 855
      def default_plugin_loader
        Plugin::Loader
      end
856 857 858 859 860 861 862 863
      
      def default_cache_store
        if File.exist?("#{root_path}/tmp/cache/")
          [ :file_store, "#{root_path}/tmp/cache/" ]
        else
          :memory_store
        end
      end
864 865 866 867
      
      def default_gems
        []
      end
868
  end
869
end
870

871
# Needs to be duplicated from Active Support since its needed before Active
872
# Support is available. Here both Options and Hash are namespaced to prevent
P
Pratik Naik 已提交
873
# conflicts with other implementations AND with the classes residing in Active Support.
874 875 876 877
class Rails::OrderedOptions < Array #:nodoc:
  def []=(key, value)
    key = key.to_sym

878 879 880 881 882 883 884 885
    if pair = find_pair(key)
      pair.pop
      pair << value
    else
      self << [key, value]
    end
  end

886
  def [](key)
887 888
    pair = find_pair(key.to_sym)
    pair ? pair.last : nil
889 890 891 892 893 894 895 896 897
  end

  def method_missing(name, *args)
    if name.to_s =~ /(.*)=$/
      self[$1.to_sym] = args.first
    else
      self[name]
    end
  end
898 899 900 901 902 903

  private
    def find_pair(key)
      self.each { |i| return i if i.first == key }
      return false
    end
904
end