Rails got a nice little bit of organizational mojo today. I’m sure we all have litterings of various configs at the bottom or our environment.rb files, like inflections, mail configs etc… Here’s the bottom of one of my projects’ environment files:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Mail ActionMailer::Base.delivery_method = :sendmail ... # Exception notification ExceptionNotifier.exception_recipients = %w(ryan@me.com) ... # Various engine configs ... # Custom date formats ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(:concise => "%d.%b.%y") .. |
Pretty ugly after the structure and conciseness of the Rails::Initializer block, huh? Well now you can place your little bits of initialization code in a config/initializers/ directory and they will get pulled in and loaded after the Rails::Initializer runs.
So now instead of polluting your environment file you can create a single file for each initialization task:
config/initializers/mail.rb:
1 2 |
ActionMailer::Base.delivery_method = :sendmail ActionMailer::Base.default_charset = "utf-8" |
config/initializers/date_formats.rb:
1 2 |
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(:concise => "%d.%b.%y") ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(:medium => "%b %e, %Y") |
Now go clean your environment file, filthy lil’ runts.
It should be noted that these initialization files are loaded at startup for all environments, it is not a place to put environment-specific (dev, test, prod etc…) configs
tags: rubyonrails, rails

Now that is sweet!
Indeed very sweet! Polluting the environment.rb with initialization code always annoyed me, so I really like this solution.
Wow, this is really nice, although some environment dependent blocks would be really nice. I don’t know if any global variable contains information about the current environment, but if so, it should not be too difficult to write some dependent code for each of them.
I think this new feature needs to be taken with a bit of salt, to be honest.
Firstly, the initialisation stuff for ActionMailer and the rest of your application has to go somewhere. Why not environment.rb? Don’t gt me wrong, I enjoy clean looking source code as much as anyone else, but if your initialisation looks messy now, with this change all you’re doing is just carefully brushing that mess under two or three different rugs.
Secondly, there’s no control over the order in which these initializers are loaded. Or – because I’m not really suggesting that there ought to be control – developers need to be aware that these files are going to be loaded in an order dictated by the filesystem, and that’s going to dictate the order in which that parts of your application are initialized. Be aware. If your Zebras need to be fed before your Aardvarks, this changeset might not help at all.
In a nutshell, I think this changeset solves a problem that wasn’t really there in the first place, and creates a non-obvious gotcha that may end up biting people. Perhaps I’m missing the point here?
i feel so dirty
I like this. The inclusion of this functionality does not remove the ability to do things like what James is referencing where order is important—you can still put initialization stuff in environment.rb. It just enables you to clean up environment.rb and break up your initialization into nice little chunks. Nice.
To address the dev/test/production issue, maybe the functionality could be expanded to load files from config/intializers/RAILS_ENV/ like it does today for environment files. Just a thought.
And don’t forget that you can always add conditional statements based on the
RAILS_ENVin your initialization files – though that doesn’t feel quite as clean.If order is important, put those statements in order in one file. Simple!
Ok, I’m now totally sold on this being a great idea. I’m not running on Edge, though, so I added this to my environment.rb:
Dir.glob(File.join(RAILS_ROOT, "config", "initializers", "*.rb")).sort.map { |initializer| require initializer }Sorting the file list allows for order control, so your initializers can look like this:
And man! That is so much nicer!
@Coda: should you be loading those files in your block instead of requiring them?
The other nice thing about this change is that those files are loaded after plugins. In rails 1.2, environment.rb is loaded before plugins. Any plugin initialization had to go in an after_initialize block.