Class: Rails::Initializer

Inherits:
Object show all
Defined in:
lib/initializer.rb

Overview

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_web_service ]
end

This will use the default configuration options from Rails::Configuration, but allow for overwriting on select areas.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(configuration) ⇒ Initializer

Create a new Initializer instance that references the given Configuration instance.



53
54
55
56
# File 'lib/initializer.rb', line 53

def initialize(configuration)
  @configuration = configuration
  @loaded_plugins = []
end

Instance Attribute Details

#configurationObject (readonly)

The Configuration instance used by this Initializer instance.



31
32
33
# File 'lib/initializer.rb', line 31

def configuration
  @configuration
end

#loaded_pluginsObject (readonly)

The set of loaded plugins.



34
35
36
# File 'lib/initializer.rb', line 34

def loaded_plugins
  @loaded_plugins
end

Class Method Details

.run(command = :process, configuration = Configuration.new) {|configuration| ... } ⇒ Object

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 incuring the overhead of completely loading the entire environment.

Yields:



44
45
46
47
48
49
# File 'lib/initializer.rb', line 44

def self.run(command = :process, configuration = Configuration.new)
  yield configuration if block_given?
  initializer = new configuration
  initializer.send(command)
  initializer
end

Instance Method Details

#add_support_load_pathsObject

Add the load paths used by support functions such as the info controller



170
171
# File 'lib/initializer.rb', line 170

def add_support_load_paths
end

#after_initializeObject

Fires the user-supplied after_initialize block (Configuration#after_initialize)



340
341
342
# File 'lib/initializer.rb', line 340

def after_initialize
  configuration.after_initialize_block.call if configuration.after_initialize_block
end

#check_ruby_versionObject

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.



124
125
126
# File 'lib/initializer.rb', line 124

def check_ruby_version
  require 'ruby_version_check'
end

#initialize_breakpointsObject

Sets the BREAKPOINT_SERVER_PORT if Configuration#breakpoint_server is true.



304
305
306
# File 'lib/initializer.rb', line 304

def initialize_breakpoints
  silence_warnings { Object.const_set("BREAKPOINT_SERVER_PORT", 42531) if configuration.breakpoint_server }
end

#initialize_databaseObject

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.



232
233
234
235
236
# File 'lib/initializer.rb', line 232

def initialize_database
  return unless configuration.frameworks.include?(:active_record)
  ActiveRecord::Base.configurations = configuration.database_configuration
  ActiveRecord::Base.establish_connection
end

#initialize_dependency_mechanismObject

Sets the dependency loading mechanism based on the value of Configuration#cache_classes.



298
299
300
# File 'lib/initializer.rb', line 298

def initialize_dependency_mechanism
  Dependencies.mechanism = configuration.cache_classes ? :require : :load
end

#initialize_encodingObject

This initialzation 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



224
225
226
# File 'lib/initializer.rb', line 224

def initialize_encoding
  $KCODE='u'
end

#initialize_framework_loggingObject

Sets the logger for ActiveRecord, ActionController, and ActionMailer (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.



271
272
273
274
275
# File 'lib/initializer.rb', line 271

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_DEFAULT_LOGGER
  end
end

#initialize_framework_settingsObject

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.



329
330
331
332
333
334
335
336
337
# File 'lib/initializer.rb', line 329

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
end

#initialize_framework_viewsObject

Sets the template_root for ActionController::Base and ActionMailer::Base (but only for those frameworks that are to be loaded). If the framework’s template_root has already been set, it is not changed, otherwise it is set to use Configuration#view_path.



281
282
283
284
285
# File 'lib/initializer.rb', line 281

def initialize_framework_views
  for framework in ([ :action_controller, :action_mailer ] & configuration.frameworks)
    framework.to_s.camelize.constantize.const_get("Base").template_root ||= configuration.view_path
  end
end

#initialize_loggerObject

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.



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/initializer.rb', line 246

def initialize_logger
  # if the environment has explicitly defined a logger, use it
  return if defined?(RAILS_DEFAULT_LOGGER)

  unless logger = configuration.logger
    begin
      logger = Logger.new(configuration.log_path)
      logger.level = Logger.const_get(configuration.log_level.to_s.upcase)
    rescue StandardError
      logger = Logger.new(STDERR)
      logger.level = Logger::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

#initialize_routingObject

If ActionController 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).



290
291
292
293
294
# File 'lib/initializer.rb', line 290

def initialize_routing
  return unless configuration.frameworks.include?(:action_controller)
  ActionController::Routing.controller_paths = configuration.controller_paths
  ActionController::Routing::Routes.reload
end

#initialize_temporary_directoriesObject



314
315
316
317
318
319
320
321
322
323
324
# File 'lib/initializer.rb', line 314

def initialize_temporary_directories
  if configuration.frameworks.include?(:action_controller)
    session_path = "#{configuration.root_path}/tmp/sessions/"
    ActionController::Base.session_options[:tmpdir] = File.exist?(session_path) ? session_path : Dir::tmpdir

    cache_path = "#{configuration.root_path}/tmp/cache/"
    if File.exist?(cache_path)
      ActionController::Base.fragment_cache_store = :file_store, cache_path
    end
  end
end

#initialize_whiny_nilsObject

Loads support for “whiny nil” (noisy warnings when methods are invoked on nil values) if Configuration#whiny_nils is true.



310
311
312
# File 'lib/initializer.rb', line 310

def initialize_whiny_nils
  require('active_support/whiny_nil') if configuration.whiny_nils
end

#load_environmentObject

Loads the environment specified by Configuration#environment_path, which is typically one of development, testing, or production.



204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/initializer.rb', line 204

def load_environment
  silence_warnings do
    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

#load_observersObject



217
218
219
# File 'lib/initializer.rb', line 217

def load_observers
  ActiveRecord::Base.instantiate_observers
end

#load_pluginsObject

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 = ['lib/plugins', 'vendor/plugins']

Each plugin discovered in plugin_paths is initialized:

  • add its lib directory, if present, to the beginning of the load path

  • evaluate init.rb 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, the plugins will be loaded in that order. Otherwise, plugins are loaded in alphabetical order.



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/initializer.rb', line 186

def load_plugins
  if configuration.plugins.nil?
    # a nil value implies we don't care about plugins; load 'em all in a reliable order
    find_plugins(configuration.plugin_paths).sort.each { |path| load_plugin path }
  elsif !configuration.plugins.empty?
    # we've specified a config.plugins array, so respect that order
    plugin_paths = find_plugins(configuration.plugin_paths)
    configuration.plugins.each do |name|
      path = plugin_paths.find { |p| File.basename(p) == name }
      raise(LoadError, "Cannot find the plugin '#{name}'!") if path.nil?
      load_plugin path
    end
  end
  $LOAD_PATH.uniq!
end

#processObject

Sequentially step through all of the available initialization routines, in order:

  • #set_load_path

  • #set_connection_adapters

  • #require_frameworks

  • #load_environment

  • #initialize_database

  • #initialize_logger

  • #initialize_framework_logging

  • #initialize_framework_views

  • #initialize_dependency_mechanism

  • #initialize_breakpoints

  • #initialize_whiny_nils

  • #initialize_framework_settings

  • #load_environment

  • #load_plugins

  • #load_observers

  • #initialize_routing

(Note that #load_environment is invoked twice, once at the start and once at the end, to support the legacy configuration style where the environment could overwrite the defaults directly, instead of via the Configuration instance.



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/initializer.rb', line 82

def process
  check_ruby_version
  set_load_path
  set_connection_adapters

  require_frameworks
  set_autoload_paths
  load_environment

  initialize_encoding
  initialize_database
  initialize_logger
  initialize_framework_logging
  initialize_framework_views
  initialize_dependency_mechanism
  initialize_breakpoints
  initialize_whiny_nils
  initialize_temporary_directories
  initialize_framework_settings

  # Support for legacy configuration style where the environment
  # could overwrite anything set from the defaults/global through
  # the individual base class configurations.
  load_environment

  add_support_load_paths

  load_plugins

  # Observers are loaded after plugins in case Observers or observed models are modified by plugins.
  load_observers

  # Routing must be initialized after plugins to allow the former to extend the routes
  initialize_routing

  # the framework is now fully initialized
  after_initialize
end

#require_frameworksObject

Requires all frameworks specified by the Configuration#frameworks list. By default, all frameworks (ActiveRecord, ActiveSupport, ActionPack, ActionMailer, and ActionWebService) are loaded.



165
166
167
# File 'lib/initializer.rb', line 165

def require_frameworks
  configuration.frameworks.each { |framework| require(framework.to_s) }
end

#set_autoload_pathsObject

Set the paths from which Rails will automatically load source files, and the load_once paths.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/initializer.rb', line 138

def set_autoload_paths
  Dependencies.load_paths = configuration.load_paths.uniq
  Dependencies.load_once_paths = configuration.load_once_paths.uniq

  extra = Dependencies.load_once_paths - 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

#set_connection_adaptersObject

Sets the RAILS_CONNECTION_ADAPTERS constant based on the value of Configuration#connection_adapters. This constant is used to determine which database adapters should be loaded (by default, all adapters are loaded).



158
159
160
# File 'lib/initializer.rb', line 158

def set_connection_adapters
  Object.const_set("RAILS_CONNECTION_ADAPTERS", configuration.connection_adapters) if configuration.connection_adapters
end

#set_load_pathObject

Set the $LOAD_PATH based on the value of Configuration#load_paths. Duplicates are removed.



130
131
132
133
134
# File 'lib/initializer.rb', line 130

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