What's New in Edge Rails: Stop Littering In Your Environment File

Posted by ryan
at 9:37 PM on Thursday, February 22, 2007

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([email protected])
...

# 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

Comments

Leave a response

  1. SamFebruary 22, 2007 @ 11:25 PM

    Now that is sweet!

  2. LudoFebruary 23, 2007 @ 03:53 AM

    Indeed very sweet! Polluting the environment.rb with initialization code always annoyed me, so I really like this solution.

  3. MaxFebruary 23, 2007 @ 04:36 AM

    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.

  4. James AdamFebruary 23, 2007 @ 04:44 AM

    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?

  5. bpFebruary 23, 2007 @ 05:01 AM

    i feel so dirty

  6. KevinFebruary 23, 2007 @ 08:24 AM

    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.

  7. Ryan DaigleFebruary 23, 2007 @ 08:58 AM

    And don’t forget that you can always add conditional statements based on the RAILS_ENV in your initialization files – though that doesn’t feel quite as clean.

  8. ScottFebruary 23, 2007 @ 06:15 PM

    If order is important, put those statements in order in one file. Simple!

  9. Coda HaleFebruary 23, 2007 @ 08:34 PM

    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:

    • 00_do_something_vital.rb
    • 01_do_something_after_vital.rb
    • whenever_you_get_a_chance.rb

    And man! That is so much nicer!

  10. Ryan DaigleFebruary 23, 2007 @ 10:19 PM

    @Coda: should you be loading those files in your block instead of requiring them?

  11. rickFebruary 26, 2007 @ 05:44 PM

    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.