web-dev-qa-db-ja.com

Rails_ENVをレーキタスクに強制するにはどうすればよいですか?

この小さなすくいのタス​​クがあります:

namespace :db do 
  namespace :test do 
    task :reset do 
      ENV['Rails_ENV'] = "test" 
      Rake::Task['db:drop'].invoke
      Rake::Task['db:create'].invoke
      Rake::Task['db:migrate'].invoke
    end
  end
end

さて、実行すると、ハードコードしようとしたRails_ENVは無視されます。このタスクを期待どおりに機能させるにはどうすればよいですか

45
Sam Saffron

この特定のタスクでは、DB接続を変更するだけでよいため、Adamが指摘したように、これを行うことができます。

namespace :db do 
  namespace :test do 
    task :reset do 
      ActiveRecord::Base.establish_connection('test')
      Rake::Task['db:drop'].invoke
      Rake::Task['db:create'].invoke
      Rake::Task['db:migrate'].invoke
      ActiveRecord::Base.establish_connection(ENV['Rails_ENV'])  #Make sure you don't have side-effects!
    end
  end
end

タスクがより複雑で、ENVの他の側面が必要な場合は、新しいrakeプロセスを最も安全に生成できます。

namespace :db do 
  namespace :test do 
    task :reset do 
      system("rake db:drop Rails_ENV=test")
      system("rake db:create Rails_ENV=test")
      system("rake db:migrate Rails_ENV=test")
    end
  end
end

または

namespace :db do 
  namespace :test do 
    task :reset do 
      if (ENV['Rails_ENV'] == "test")
        Rake::Task['db:drop'].invoke
        Rake::Task['db:create'].invoke
        Rake::Task['db:migrate'].invoke
      else
        system("rake db:test:reset Rails_ENV=test")
      end
    end
  end
end
50
Michael Sofaer

Rails 3では、使用する必要があります

Rails.env = "test"
Rake::Task["db:drop"].invoke

の代わりに

Rails_ENV = "test"
Rake::Task["db:drop"].invoke 
19
yacc

別のオプションは、envを確認して続行を拒否することです。

unless Rails.env.development?
  puts "This task can only be run in development environment"
  exit
end

または、本当に続行したいかどうかを尋ねます。

unless Rails.env.development?
  puts "You are using #{Rails.env} environment, are you sure? y/n"
  continue = STDIN.gets.chomp
  exit unless continue == 'y'
end
11
Kris

最もクリーンでシンプルなソリューションは、Rails_ENVENV['Rails_ENV']ではなく)を再定義することです。

namespace :db do
  namespace :test do  
    task :reset do 
      Rails_ENV = "test" 
      Rake::Task['db:drop'].invoke
      Rake::Task['db:create'].invoke
      Rake::Task['db:migrate'].invoke
    end
  end
end

Rails application Rails_ENVは次のように初期化されます。

Rails_ENV = (ENV['Rails_ENV'] || 'development').dup unless defined?(Rails_ENV)

残りのRailsコードはRails_ENVを直接使用します。

ただし、マイケルが自分の答えへのコメントで指摘したように、Rails_ENVをその場で切り替えることは危険です。別のアプローチは、データベース接続を切り替えることです。実際、このソリューションはデフォルトのdb:testタスクで使用されます

ActiveRecord::Base.establish_connection(:test)
6
Adam Byrtek

もちろん、最良の方法は、rakeタスクを実行するときにコマンドラインから環境を指定することですが、何らかの理由でそれがしたくない場合は、これを行うことができます:

ENV["Rails_ENV"] = 'test'
Rails_ENV.replace('test') if defined?(Rails_ENV)

load "#{Rails_ROOT}/config/environment.rb"

そして、これでうまくいくはずです。

4
ealdent

database_tasks.rbには奇妙なコードがあります:

  def each_current_configuration(environment)
    environments = [environment]
    environments << 'test' if environment == 'development'

    configurations = ActiveRecord::Base.configurations.values_at(*environments)
    configurations.compact.each do |configuration|
      yield configuration unless configuration['database'].blank?
    end
  end

Envがtestの場合、常にdevelopmentを追加します。最初にdevelopmentを実行し、次にtestを実行することにより、developmenttestを同時に処理するカスタムdb:rebuildタスクを実行したい場合の問題を解決しました。さらに、タスクを実行する前に、set_envメソッドを呼び出してActiveRecord::Tasks::DatabaseTasks.envを設定します。これがないと、データベース接続は期待どおりに環境で個別に処理されないようです。他のすべての種類の切断などを試しましたが、これはそれ以上のコードなしで機能しました。

def set_env(env)
  Rails.env = env.to_s
  ENV['Rails_ENV'] = env.to_s
  ActiveRecord::Tasks::DatabaseTasks.env = env.to_s
end

ここに、同時マルチ環境db.rakedb:rebuildを含む完全なdb:truncateファイルの要点があります

3
kross