如何强制RAILS_ENV在耙子任务吗?如何强制RAILS_ENV在耙子任务吗?(How do I

2019-05-17 07:47发布

我有这个小耙子任务:

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。 如何使这项工作按预期方式工作

Answer 1:

对于这个特殊的任务,你只需要改变数据库连接,从而亚当指出的那样,你可以这样做:

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的其他方面,你是最安全产生一个新的耙过程:

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


Answer 2:

在Rails 3,你将不得不使用

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

代替

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


Answer 3:

另一种方法是检查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


Answer 4:

最清洁和最简单的解决办法是重新定义RAILS_ENV (未ENV['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应用程序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)


Answer 5:

当然,最好的办法是从指定当您运行rake任务的命令行环境,但如果由于某种原因,你想做的事,这不是,你可以这样做:

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

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

这应该做的伎俩。



Answer 6:

有一些奇怪的代码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

它总是添加test ,如果ENV是development 。 我解决了想要做一个自定义的情况下db:rebuild的任务,同时developmenttest运行development第一,并test第二。 此外,在运行任务之前,我打电话给我的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.rake与同时多环境文件db:rebuilddb:truncate



文章来源: How do I force RAILS_ENV in a rake task?