29
votes

I need to run a series of Rake tasks from another Rake task. The first three tasks need to be run in the development environment, but the final task needs to be run in the staging environment. The task has a dependency on :environment which causes the Rails development environment to be loaded before the tasks run.

However, I need the final task to be executed in the staging environment.

Passing a RAILS_ENV=staging flag before invoking the rake task is no good as the environment has already loaded at this point and all this will do is set the flag, not load the staging environment.

Is there a way I can force a rake task in a specific environment?

2
You probably can't, because environment settings are global. You can do it through a separate system call, such as system({RAILS_ENV: 'staging'}, "rake staging_command").Leonid Shevtsov
@LeonidShevtsov I'm actually using system, but it doesn't reload the environment.Undistraction
What do you mean by 'reload the environment'? It does reload the Ruby interpreter along with the entire application. What else should be reloaded?Leonid Shevtsov
I mean that a new instance of the Rails app isn't loaded before the rake task runs. I can clearly see this by logging from application.rb which is not loaded a second time.Undistraction
Are you sure you're looking at the correct log for the staging environment?Leonid Shevtsov

2 Answers

21
votes

I've accomplished this kind of this before, albeit not in the most elegant of ways:

task :prepare do
  system("bundle exec rake ... RAILS_ENV=development")      
  system("bundle exec rake ... RAILS_ENV=development")
  system("bundle exec rake ... RAILS_ENV=test")
  system("bundle exec rake ... RAILS_ENV=test")
  system("bundle exec rake ... RAILS_ENV=test")
  system("bundle exec rake ... RAILS_ENV=test")
end

It's always worked for me. I'd be curious to know if there was a better way.

15
votes

The way I solved it was to add a dependency to set the rails env before the task is invoked:

namespace :foo do
  desc "Our custom rake task"
  task :bar => ["db:test:set_test_env", :environment] do
      puts "Custom rake task"
      # Do whatever here...
      puts Rails.env
  end
end


namespace :db do
  namespace :test do
    desc "Custom dependency to set test environment"
    task :set_test_env do # Note that we don't load the :environment task dependency
      Rails.env = "test"
    end
  end
end