Upgraded Rails and RSpec
[monkeycharger.git] / vendor / rails / railties / lib / initializer.rb
blobab6549164cc10e20f490164342d89ca147e2347a
1 require 'logger'
2 require 'set'
3 require 'pathname'
5 $LOAD_PATH.unshift File.dirname(__FILE__)
6 require 'railties_path'
7 require 'rails/version'
8 require 'rails/plugin/locator'
9 require 'rails/plugin/loader'
12 RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV)
14 module Rails
15   # The Initializer is responsible for processing the Rails configuration, such
16   # as setting the $LOAD_PATH, requiring the right frameworks, initializing
17   # logging, and more. It can be run either as a single command that'll just
18   # use the default configuration, like this:
19   #
20   #   Rails::Initializer.run
21   #
22   # But normally it's more interesting to pass in a custom configuration
23   # through the block running:
24   #
25   #   Rails::Initializer.run do |config|
26   #     config.frameworks -= [ :action_mailer ]
27   #   end
28   #
29   # This will use the default configuration options from Rails::Configuration,
30   # but allow for overwriting on select areas.
31   class Initializer
32     # The Configuration instance used by this Initializer instance.
33     attr_reader :configuration
35     # The set of loaded plugins.
36     attr_reader :loaded_plugins
37     
38     # Runs the initializer. By default, this will invoke the #process method,
39     # which simply executes all of the initialization routines. Alternately,
40     # you can specify explicitly which initialization routine you want:
41     #
42     #   Rails::Initializer.run(:set_load_path)
43     #
44     # This is useful if you only want the load path initialized, without
45     # incuring the overhead of completely loading the entire environment.
46     def self.run(command = :process, configuration = Configuration.new)
47       yield configuration if block_given?
48       initializer = new configuration
49       initializer.send(command)
50       initializer
51     end
53     # Create a new Initializer instance that references the given Configuration
54     # instance.
55     def initialize(configuration)
56       @configuration = configuration
57       @loaded_plugins = []
58     end
60     # Sequentially step through all of the available initialization routines,
61     # in order:
62     #
63     # * #check_ruby_version
64     # * #set_load_path
65     # * #require_frameworks
66     # * #set_autoload_paths
67     # * add_plugin_load_paths
68     # * #load_environment
69     # * #initialize_encoding
70     # * #initialize_database
71     # * #initialize_logger
72     # * #initialize_framework_logging
73     # * #initialize_framework_views
74     # * #initialize_dependency_mechanism
75     # * #initialize_whiny_nils
76     # * #initialize_temporary_directories
77     # * #initialize_framework_settings
78     # * #add_support_load_paths
79     # * #load_plugins
80     # * #load_observers
81     # * #initialize_routing
82     # * #after_initialize
83     # * #load_application_initializers
84     def process
85       check_ruby_version
86       set_load_path
87       
88       require_frameworks
89       set_autoload_paths
90       add_plugin_load_paths
91       load_environment
93       initialize_encoding
94       initialize_database
95       initialize_logger
96       initialize_framework_logging
97       initialize_framework_views
98       initialize_dependency_mechanism
99       initialize_whiny_nils
100       initialize_temporary_directories
101       initialize_framework_settings
103       add_support_load_paths
105       load_plugins
107       # Observers are loaded after plugins in case Observers or observed models are modified by plugins.
108       load_observers
110       # Routing must be initialized after plugins to allow the former to extend the routes
111       initialize_routing
113       # the framework is now fully initialized
114       after_initialize
116       load_application_initializers
117     end
119     # Check for valid Ruby version
120     # This is done in an external file, so we can use it
121     # from the `rails` program as well without duplication.
122     def check_ruby_version
123       require 'ruby_version_check'
124     end
126     # Set the <tt>$LOAD_PATH</tt> based on the value of
127     # Configuration#load_paths. Duplicates are removed.
128     def set_load_path
129       load_paths = configuration.load_paths + configuration.framework_paths
130       load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) }
131       $LOAD_PATH.uniq!
132     end
134     # Set the paths from which Rails will automatically load source files, and
135     # the load_once paths.
136     def set_autoload_paths
137       Dependencies.load_paths = configuration.load_paths.uniq
138       Dependencies.load_once_paths = configuration.load_once_paths.uniq
140       extra = Dependencies.load_once_paths - Dependencies.load_paths
141       unless extra.empty?
142         abort <<-end_error
143           load_once_paths must be a subset of the load_paths.
144           Extra items in load_once_paths: #{extra * ','}
145         end_error
146       end
148       # Freeze the arrays so future modifications will fail rather than do nothing mysteriously
149       configuration.load_once_paths.freeze
150     end
152     # Requires all frameworks specified by the Configuration#frameworks
153     # list. By default, all frameworks (ActiveRecord, ActiveSupport,
154     # ActionPack, ActionMailer, and ActiveResource) are loaded.
155     def require_frameworks
156       configuration.frameworks.each { |framework| require(framework.to_s) }
157     rescue LoadError => e
158       # re-raise because Mongrel would swallow it
159       raise e.to_s
160     end
162     # Add the load paths used by support functions such as the info controller
163     def add_support_load_paths
164     end
166     # Adds all load paths from plugins to the global set of load paths, so that
167     # code from plugins can be required (explicitly or automatically via Dependencies).
168     def add_plugin_load_paths
169       plugin_loader.add_plugin_load_paths
170     end
172     # Loads all plugins in <tt>config.plugin_paths</tt>.  <tt>plugin_paths</tt>
173     # defaults to <tt>vendor/plugins</tt> but may also be set to a list of
174     # paths, such as
175     #   config.plugin_paths = ["#{RAILS_ROOT}/lib/plugins", "#{RAILS_ROOT}/vendor/plugins"]
176     #
177     # In the default implementation, as each plugin discovered in <tt>plugin_paths</tt> is initialized:
178     # * its +lib+ directory, if present, is added to the load path (immediately after the applications lib directory)
179     # * <tt>init.rb</tt> is evalutated, if present
180     #
181     # After all plugins are loaded, duplicates are removed from the load path.
182     # If an array of plugin names is specified in config.plugins, only those plugins will be loaded
183     # and they plugins will be loaded in that order. Otherwise, plugins are loaded in alphabetical
184     # order.
185     #
186     # if config.plugins ends contains :all then the named plugins will be loaded in the given order and all other
187     # plugins will be loaded in alphabetical order
188     def load_plugins
189       plugin_loader.load_plugins
190     end
192     def plugin_loader
193       @plugin_loader ||= configuration.plugin_loader.new(self)
194     end
196     # Loads the environment specified by Configuration#environment_path, which
197     # is typically one of development, test, or production.
198     def load_environment
199       silence_warnings do
200         return if @environment_loaded
201         @environment_loaded = true
202         
203         config = configuration
204         constants = self.class.constants
205         
206         eval(IO.read(configuration.environment_path), binding, configuration.environment_path)
207         
208         (self.class.constants - constants).each do |const|
209           Object.const_set(const, self.class.const_get(const))
210         end
211       end
212     end
214     def load_observers
215       if configuration.frameworks.include?(:active_record)
216         ActiveRecord::Base.instantiate_observers
217       end
218     end
220     # This initialzation sets $KCODE to 'u' to enable the multibyte safe operations.
221     # Plugin authors supporting other encodings should override this behaviour and
222     # set the relevant +default_charset+ on ActionController::Base
223     def initialize_encoding
224       $KCODE='u'
225     end
227     # This initialization routine does nothing unless <tt>:active_record</tt>
228     # is one of the frameworks to load (Configuration#frameworks). If it is,
229     # this sets the database configuration from Configuration#database_configuration
230     # and then establishes the connection.
231     def initialize_database
232       if configuration.frameworks.include?(:active_record)
233         ActiveRecord::Base.configurations = configuration.database_configuration
234         ActiveRecord::Base.establish_connection
235       end
236     end
238     # If the +RAILS_DEFAULT_LOGGER+ constant is already set, this initialization
239     # routine does nothing. If the constant is not set, and Configuration#logger
240     # is not +nil+, this also does nothing. Otherwise, a new logger instance
241     # is created at Configuration#log_path, with a default log level of
242     # Configuration#log_level.
243     #
244     # If the log could not be created, the log will be set to output to
245     # +STDERR+, with a log level of +WARN+.
246     def initialize_logger
247       # if the environment has explicitly defined a logger, use it
248       return if defined?(RAILS_DEFAULT_LOGGER)
250       unless logger = configuration.logger
251         begin
252           logger = ActiveSupport::BufferedLogger.new(configuration.log_path)
253           logger.level = ActiveSupport::BufferedLogger.const_get(configuration.log_level.to_s.upcase)
254           logger.auto_flushing = false if configuration.environment == "production"
255         rescue StandardError =>e
256           logger = ActiveSupport::BufferedLogger.new(STDERR)
257           logger.level = ActiveSupport::BufferedLogger::WARN
258           logger.warn(
259             "Rails Error: Unable to access log file. Please ensure that #{configuration.log_path} exists and is chmod 0666. " +
260             "The log level has been raised to WARN and the output directed to STDERR until the problem is fixed."
261           )
262         end
263       end
265       silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
266     end
268     # Sets the logger for ActiveRecord, ActionController, and ActionMailer
269     # (but only for those frameworks that are to be loaded). If the framework's
270     # logger is already set, it is not changed, otherwise it is set to use
271     # +RAILS_DEFAULT_LOGGER+.
272     def initialize_framework_logging
273       for framework in ([ :active_record, :action_controller, :action_mailer ] & configuration.frameworks)
274         framework.to_s.camelize.constantize.const_get("Base").logger ||= RAILS_DEFAULT_LOGGER
275       end
276     end
278     # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+
279     # (but only for those frameworks that are to be loaded). If the framework's
280     # paths have already been set, it is not changed, otherwise it is
281     # set to use Configuration#view_path.
282     def initialize_framework_views
283       ActionMailer::Base.template_root ||= configuration.view_path  if configuration.frameworks.include?(:action_mailer)
284       ActionController::Base.view_paths = [configuration.view_path] if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.empty?
285     end
287     # If ActionController is not one of the loaded frameworks (Configuration#frameworks)
288     # this does nothing. Otherwise, it loads the routing definitions and sets up
289     # loading module used to lazily load controllers (Configuration#controller_paths).
290     def initialize_routing
291       return unless configuration.frameworks.include?(:action_controller)
292       ActionController::Routing.controller_paths = configuration.controller_paths
293       ActionController::Routing::Routes.reload
294     end
296     # Sets the dependency loading mechanism based on the value of
297     # Configuration#cache_classes.
298     def initialize_dependency_mechanism
299       Dependencies.mechanism = configuration.cache_classes ? :require : :load
300     end
302     # Loads support for "whiny nil" (noisy warnings when methods are invoked
303     # on +nil+ values) if Configuration#whiny_nils is true.
304     def initialize_whiny_nils
305       require('active_support/whiny_nil') if configuration.whiny_nils
306     end
308     def initialize_temporary_directories
309       if configuration.frameworks.include?(:action_controller)
310         session_path = "#{configuration.root_path}/tmp/sessions/"
311         ActionController::Base.session_options[:tmpdir] = File.exist?(session_path) ? session_path : Dir::tmpdir
313         cache_path = "#{configuration.root_path}/tmp/cache/"
314         if File.exist?(cache_path)
315           ActionController::Base.fragment_cache_store = :file_store, cache_path
316         end
317       end
318     end
320     # Initializes framework-specific settings for each of the loaded frameworks
321     # (Configuration#frameworks). The available settings map to the accessors
322     # on each of the corresponding Base classes.
323     def initialize_framework_settings
324       configuration.frameworks.each do |framework|
325         base_class = framework.to_s.camelize.constantize.const_get("Base")
327         configuration.send(framework).each do |setting, value|
328           base_class.send("#{setting}=", value)
329         end
330       end
331     end
333     # Fires the user-supplied after_initialize block (Configuration#after_initialize)
334     def after_initialize
335       configuration.after_initialize_blocks.each do |block|
336         block.call
337       end
338     end
340     def load_application_initializers
341       Dir["#{configuration.root_path}/config/initializers/**/*.rb"].sort.each do |initializer|
342         load(initializer)
343       end
344     end
346   end
348   # The Configuration class holds all the parameters for the Initializer and
349   # ships with defaults that suites most Rails applications. But it's possible
350   # to overwrite everything. Usually, you'll create an Configuration file
351   # implicitly through the block running on the Initializer, but it's also
352   # possible to create the Configuration instance in advance and pass it in
353   # like this:
354   #
355   #   config = Rails::Configuration.new
356   #   Rails::Initializer.run(:process, config)
357   class Configuration
358     # The application's base directory.
359     attr_reader :root_path
361     # A stub for setting options on ActionController::Base
362     attr_accessor :action_controller
364     # A stub for setting options on ActionMailer::Base
365     attr_accessor :action_mailer
367     # A stub for setting options on ActionView::Base
368     attr_accessor :action_view
370     # A stub for setting options on ActiveRecord::Base
371     attr_accessor :active_record
373     # A stub for setting options on ActiveRecord::Base
374     attr_accessor :active_resource
376     # Whether or not classes should be cached (set to false if you want
377     # application classes to be reloaded on each request)
378     attr_accessor :cache_classes
380     # The list of paths that should be searched for controllers. (Defaults
381     # to <tt>app/controllers</tt> and <tt>components</tt>.)
382     attr_accessor :controller_paths
384     # The path to the database configuration file to use. (Defaults to
385     # <tt>config/database.yml</tt>.)
386     attr_accessor :database_configuration_file
388     # The list of rails framework components that should be loaded. (Defaults
389     # to <tt>:active_record</tt>, <tt>:action_controller</tt>,
390     # <tt>:action_view</tt>, <tt>:action_mailer</tt>, and
391     # <tt>:active_resource</tt>).
392     attr_accessor :frameworks
394     # An array of additional paths to prepend to the load path. By default,
395     # all +app+, +lib+, +vendor+ and mock paths are included in this list.
396     attr_accessor :load_paths
398     # An array of paths from which Rails will automatically load from only once.
399     # All elements of this array must also be in +load_paths+.
400     attr_accessor :load_once_paths
402     # The log level to use for the default Rails logger. In production mode,
403     # this defaults to <tt>:info</tt>. In development mode, it defaults to
404     # <tt>:debug</tt>.
405     attr_accessor :log_level
407     # The path to the log file to use. Defaults to log/#{environment}.log
408     # (e.g. log/development.log or log/production.log).
409     attr_accessor :log_path
411     # The specific logger to use. By default, a logger will be created and
412     # initialized using #log_path and #log_level, but a programmer may
413     # specifically set the logger to use via this accessor and it will be
414     # used directly.
415     attr_accessor :logger
417     # The root of the application's views. (Defaults to <tt>app/views</tt>.)
418     attr_accessor :view_path
420     # Set to +true+ if you want to be warned (noisily) when you try to invoke
421     # any method of +nil+. Set to +false+ for the standard Ruby behavior.
422     attr_accessor :whiny_nils
424     # The list of plugins to load. If this is set to <tt>nil</tt>, all plugins will
425     # be loaded. If this is set to <tt>[]</tt>, no plugins will be loaded. Otherwise,
426     # plugins will be loaded in the order specified.
427     attr_reader :plugins
428     def plugins=(plugins)
429       @plugins = plugins.nil? ? nil : plugins.map { |p| p.to_sym }
430     end
432     # The path to the root of the plugins directory. By default, it is in
433     # <tt>vendor/plugins</tt>.
434     attr_accessor :plugin_paths
436     # The classes that handle finding the desired plugins that you'd like to load for
437     # your application. By default it is the Rails::Plugin::FileSystemLocator which finds
438     # plugins to load in <tt>vendor/plugins</tt>. You can hook into gem location by subclassing
439     # Rails::Plugin::Locator and adding it onto the list of <tt>plugin_locators</tt>.
440     attr_accessor :plugin_locators
442     # The class that handles loading each plugin. Defaults to Rails::Plugin::Loader, but
443     # a sub class would have access to fine grained modification of the loading behavior. See
444     # the implementation of Rails::Plugin::Loader for more details.
445     attr_accessor :plugin_loader
446     
447     # Deprecated options:
448     def breakpoint_server(_ = nil)
449       $stderr.puts %(
450       *******************************************************************
451       * config.breakpoint_server has been deprecated and has no effect. *
452       *******************************************************************
453       )
454     end
455     alias_method :breakpoint_server=, :breakpoint_server
457     # Create a new Configuration instance, initialized with the default
458     # values.
459     def initialize
460       set_root_path!
462       self.frameworks                   = default_frameworks
463       self.load_paths                   = default_load_paths
464       self.load_once_paths              = default_load_once_paths
465       self.log_path                     = default_log_path
466       self.log_level                    = default_log_level
467       self.view_path                    = default_view_path
468       self.controller_paths             = default_controller_paths
469       self.cache_classes                = default_cache_classes
470       self.whiny_nils                   = default_whiny_nils
471       self.plugins                      = default_plugins
472       self.plugin_paths                 = default_plugin_paths
473       self.plugin_locators              = default_plugin_locators
474       self.plugin_loader                = default_plugin_loader
475       self.database_configuration_file  = default_database_configuration_file
477       for framework in default_frameworks
478         self.send("#{framework}=", Rails::OrderedOptions.new)
479       end
480     end
482     # Set the root_path to RAILS_ROOT and canonicalize it.
483     def set_root_path!
484       raise 'RAILS_ROOT is not set' unless defined?(::RAILS_ROOT)
485       raise 'RAILS_ROOT is not a directory' unless File.directory?(::RAILS_ROOT)
487       @root_path =
488         # Pathname is incompatible with Windows, but Windows doesn't have
489         # real symlinks so File.expand_path is safe.
490         if RUBY_PLATFORM =~ /(:?mswin|mingw)/
491           File.expand_path(::RAILS_ROOT)
493         # Otherwise use Pathname#realpath which respects symlinks.
494         else
495           Pathname.new(::RAILS_ROOT).realpath.to_s
496         end
497       
498       Object.const_set(:RELATIVE_RAILS_ROOT, ::RAILS_ROOT.dup) unless defined?(::RELATIVE_RAILS_ROOT)
499       ::RAILS_ROOT.replace @root_path
500     end
502     # Loads and returns the contents of the #database_configuration_file. The
503     # contents of the file are processed via ERB before being sent through
504     # YAML::load.
505     def database_configuration
506       YAML::load(ERB.new(IO.read(database_configuration_file)).result)
507     end
509     # The path to the current environment's file (development.rb, etc.). By
510     # default the file is at <tt>config/environments/#{environment}.rb</tt>.
511     def environment_path
512       "#{root_path}/config/environments/#{environment}.rb"
513     end
515     # Return the currently selected environment. By default, it returns the
516     # value of the +RAILS_ENV+ constant.
517     def environment
518       ::RAILS_ENV
519     end
521     # Adds a block which will be executed after rails has been fully initialized.
522     # Useful for per-environment configuration which depends on the framework being
523     # fully initialized.
524     def after_initialize(&after_initialize_block)
525       after_initialize_blocks << after_initialize_block if after_initialize_block
526     end
528     # Returns the blocks added with Configuration#after_initialize
529     def after_initialize_blocks
530       @after_initialize_blocks ||= []
531     end
533     # Add a preparation callback that will run before every request in development
534     # mode, or before the first request in production.
535     #
536     # See Dispatcher#to_prepare.
537     def to_prepare(&callback)
538       require 'dispatcher' unless defined?(::Dispatcher)
539       Dispatcher.to_prepare(&callback)
540     end
542     def builtin_directories
543       # Include builtins only in the development environment.
544       (environment == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : []
545     end
547     def framework_paths
548       paths = %w(railties railties/lib activesupport/lib)
549       paths << 'actionpack/lib' if frameworks.include? :action_controller or frameworks.include? :action_view
550       
551       [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework|
552         paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include? framework
553       end
554       
555       paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
556     end
558     private
559       def framework_root_path
560         defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails"
561       end
563       def default_frameworks
564         [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ]
565       end
567       def default_load_paths
568         paths = ["#{root_path}/test/mocks/#{environment}"]
570         # Add the app's controller directory
571         paths.concat(Dir["#{root_path}/app/controllers/"])
573         # Then components subdirectories.
574         paths.concat(Dir["#{root_path}/components/[_a-z]*"])
576         # Followed by the standard includes.
577         paths.concat %w(
578           app
579           app/models
580           app/controllers
581           app/helpers
582           app/services
583           components
584           config
585           lib
586           vendor
587         ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
589         paths.concat builtin_directories
590       end
592       # Doesn't matter since plugins aren't in load_paths yet.
593       def default_load_once_paths
594         []
595       end
597       def default_log_path
598         File.join(root_path, 'log', "#{environment}.log")
599       end
601       def default_log_level
602         environment == 'production' ? :info : :debug
603       end
605       def default_database_configuration_file
606         File.join(root_path, 'config', 'database.yml')
607       end
609       def default_view_path
610         File.join(root_path, 'app', 'views')
611       end
613       def default_controller_paths
614         paths = [File.join(root_path, 'app', 'controllers')]
615         paths.concat builtin_directories
616         paths
617       end
619       def default_dependency_mechanism
620         :load
621       end
623       def default_cache_classes
624         false
625       end
627       def default_whiny_nils
628         false
629       end
631       def default_plugins
632         nil
633       end
635       def default_plugin_paths
636         ["#{root_path}/vendor/plugins"]
637       end
639       def default_plugin_locators
640         [Plugin::FileSystemLocator]
641       end
643       def default_plugin_loader
644         Plugin::Loader
645       end
646   end
649 # Needs to be duplicated from Active Support since its needed before Active
650 # Support is available. Here both Options and Hash are namespaced to prevent
651 # conflicts with other implementations AND with the classes residing in ActiveSupport.
652 class Rails::OrderedOptions < Array #:nodoc:
653   def []=(key, value)
654     key = key.to_sym
656     if pair = find_pair(key)
657       pair.pop
658       pair << value
659     else
660       self << [key, value]
661     end
662   end
664   def [](key)
665     pair = find_pair(key.to_sym)
666     pair ? pair.last : nil
667   end
669   def method_missing(name, *args)
670     if name.to_s =~ /(.*)=$/
671       self[$1.to_sym] = args.first
672     else
673       self[name]
674     end
675   end
677   private
678     def find_pair(key)
679       self.each { |i| return i if i.first == key }
680       return false
681     end