Getting rake db:seed and config.threadsafe! to play nice

If you’ve enabled config.threadsafe! in your Rails production environment, the chances are good that you’ll encounter a confusing “uninitialized constant” error when you try to seed your database using rake db:seed.

The fact is Rails’ thread safety mode does not work with rake db:seed. No need to disable this option entirely, though. With a small modification to your environment and a simple Rake task, you’ll be good to go.

# config/environments/production.rb

# Enable threaded mode
config.threadsafe! unless ENV['THREADSAFE'] == 'off'
# lib/tasks/threadsafe.rake

namespace :threadsafe do
# desc 'Enable thread-safe mode (enabled by default in production)'
task :enabled do
ENV.delete 'THREADSAFE'
end

# desc 'Disable thread-safe mode'
task :disabled do
ENV['THREADSAFE'] = 'off'
end
end

# Ensure we are always running in single-threaded mode for Rake tasks
Rake::Task['environment'].prerequisites.insert(0, 'threadsafe:disabled')

We’re using an environment variable to tell our application whether we want to enable threaded mode or not, then disabling for all tasks that depend on the Rails environment. You can also specify it manually on the command line if you prefer that instead of making it a dependency for :environment (e.g., RAILS_ENV=production rake threadsafe:disabled db:seed).

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

5 comments

  1. Thanks for this post!

    I’ve been seeing the same error in other rake tasks including db:migrate ( when I refer to models in the migration). The previous workaround was to actually modify the environment file before and after to comment out the threadsafe line for the migrate, then enable the line for the deploy.

    Suffice to say, this works much better.

  2. I find setting this scheme of setting a system environment variable as a super global a bit heavy.

    Rake already sets a Ruby global: $rails_rake_task

    So, in config/environments/production.rb, just say:

      config.threadsafe! unless $rails_rake_task

    No other magic is required.

  3. Thanks for sharing this… If run in trouble after updated my Application in production.

  4. s/engine_name.downcase/engine_name.underscore/g

Leave a comment