Rails initialization and configuration order

will.bryant

One of the great things about Ruby frameworks is that we use Ruby code to configure and initialize all the other Ruby code, so you don't need to mess about with endless XML configuration files and write wrapper classes just to run some little bit of arbitrary code to setup your application when the server starts up.

Ruby on Rails is also built with the expectation that some of your configuration and setup will be different in your various environments - for example, you'll probably load extra debugging libraries in development mode, and you'll often set flags to disable things like real outgoing emails in development and test mode, or disable database reloads in production to prevent accidents.

So Rails provides you with convenient ways to separate out the initialization code for different environments using a separate environment file for each in config/environments, while common setup (shared gems, or plugin load order, for example) can go in environment.rb so you don't have to duplicate content anywhere.

To provide further flexibility, you can also create initializers, .rb files in config/initializers that are also run during the startup sequence. This is very convenient when you want to deploy an extra wodge of code in only some places - for example, staging instead of production, or vice versa.

So there's a range of options which cover all the different requirements projects have as far as different configurations in different environments or deployments etc., and we'll see one more in a moment.

But if you find yourself configuring things that are themselves set up by Rails during initialization/startup, you'll need to know what order those parts of the startup process occur in. For example, if you have a credit card payment processing plugin, you'll almost certainly need to set up the merchant account configuration during your application startup.

Using environment files

If the plugin expects you to have defined the configuration by say setting constants for it, you'd need to put the configuration directives in the environment configuration files (production.rb/development.rb/test.rb, or environment.rb if you're sure you want the same configuration in each environment); these files are run before plugins initialize.

# development.rb
MY_MERCHANT_ID = 600000
# production.rb
MY_MERCHANT_ID = 654321
# my_plugin/init.rb
.. use MY_MERCHANT_ID ...

Using initializer files

If on the other hand you need to wait for the plugin to be loaded before you can set up the configuration, for example creating an instance of some configuration class that the plugin itself defines, you should probably use an initializer file instead:

# my_plugin/init.rb
.. load or define class MerchantAccount ..
# config/initializer/setup_our_merchant_account.rb
OUR_MERCHANT_ACCOUNT = MerchantAccount.new(...)

So initializer files are convenient whenever you want to stick in extra configuration stuff during deployment without going to the extent of template files, and they're also useful when you need to do something on application startup after loading gems and plugins.

Using after_initialize blocks

Those initializer files have their place, but there's a final option that combines the convenience of the multiple environment files with the execution order of the initalizers: after_initialize blocks, for example:

# my_plugin/init.rb
.. load or define class MerchantAccount ..
# development.rb
config.after_initialize do
  OUR_MERCHANT_ACCOUNT = MerchantAccount.new(600000)
end
# production.rb
config.after_initialize do
  OUR_MERCHANT_ACCOUNT = MerchantAccount.new(654321)
end

Although few projects need it, this is a handy feature, and they're particularly useful if there's some things that you need to before the gems/plugins are loaded and some related things you need to do after.

Pre-initializers

Finally, for those rare projects that just gotta be different, you can put any code that needs to be run before Rails even loads itself in a file called config/preinitializer.rb. Unless you're writing a packaging system yourself, you shouldn't need to go there!

The configuration order

So here's the full detailed order these user-editable configuration files are run in, as of Rails 2.3.3. The Rails::Initializer.run call in environment.rb invokes most of these steps, which is why if you put any junk down the bottom of that file it'll actually run after everything else - one should not normally be putting anything down there.

  1. config/preinitializer.rb
  2. config/environment.rb
  3. config/environments/#{RAILS_ENV}.rb
  4. plugin initialization
  5. gem initialization
  6. config/initializer/*.rb
  7. all after_initialize blocks, in the order they were defined in (so same order as above)
  8. any junk left below the Rails::Initializer.run call/block in environment.rb

Configuring Ruby on Rails

That wraps up the general details of where to configure your own applications and plugins.

If you're interested in finding out more about configuring the Rails framework itself, check out the Configuring Rails Applications guide put together by the RailsGuides project.

Comments

  • (We won't give out your email, but it helps filter spam.)