我有这个小小的佣金任务:
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。如何使此任务按预期工作
答案 0 :(得分:49)
对于此特定任务,您只需要更改数据库连接,正如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
答案 1 :(得分:19)
在Rails 3中,你必须使用
Rails.env = "test"
Rake::Task["db:drop"].invoke
而不是
RAILS_ENV = "test"
Rake::Task["db:drop"].invoke
答案 2 :(得分:10)
另一种选择是检查环境并拒绝继续:
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
答案 3 :(得分:6)
最干净,最简单的解决方案是重新定义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)
答案 4 :(得分:4)
当然,最好的方法是在运行rake任务时从命令行指定环境,但如果由于某种原因这不是你想要做的,你可以这样做:
ENV["RAILS_ENV"] = 'test'
RAILS_ENV.replace('test') if defined?(RAILS_ENV)
load "#{RAILS_ROOT}/config/environment.rb"
这应该可以解决问题。
答案 5 :(得分:3)
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
。我通过首先运行db:rebuild
和development
秒来解决了希望同时为test
和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