Avoid DB calls when setting up your environment
December 09, 2006 18:57 (Sydney Australia)
As one of my projects has increased in complexity I’ve started to use the environment.rb and the other specific environments to set up mocks and other tidbits.
For example, here I’m setting the currentLocale based on RegionPreference, which is an ActiveRecord model, from within environment.rb:
Locales.current = Locales.locale_for_timezone(RegionPreference.find_or_initialize.timezone) rescue nil
This was all fine and dandy until I tried to set the app on a new machine.
$ rake db:schema:load RAILS_ENV=staging
(in /usr/home/voicebox)
rake aborted!
SQLite3::SQLException: no such table: region_preferences:
SELECT * FROM region_preferences LIMIT 1
What happened?
db:schema:load depends on the environment task, which loads your Rails environment. The same goes for db:migrate. My environment was being loaded and trying to call the database before db:schema:load could do it’s job.
Lesson: Accessing your database from within your environment set up is evil.
You can’t assume your database exists, or is an up-to-date version, when your environment’s are being executed.
The fix? Moving the code to the model where it should have been in the first place.
module Locales
def self.current
@@current ||= locale_for_timezone(RegionPreference.find_or_initialize.timezone)
end
end

Comments
James Adam
I’m not sure that I’d agree it’s evil to do these things in environment/* – just that Rails doesn’t support it. Here’s hoping that 2.0 will bring a reconsidered startup routine that makes what seems natural, actually possible :)
Alex Fetcher
Great site!
7003be4590c25f75bcec72c05e4c44f4
To comment on this article you must have javascript enabled.