2009-07-07 10 views
43

tengo esta pequeña tarea rake:¿Cómo fuerzo a RAILS_ENV en una tarea de rake?

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 

Ahora, cuando yo haga, se ignorará la RAILS_ENV Traté de codificar. Cómo hago que esta tarea funcione como se espera

Respuesta

48

Para esta tarea en particular, sólo es necesario cambiar la conexión de base de datos, así como Adán señaló, se puede hacer esto:

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 

Si su tarea es más complicada, y que necesita otros aspectos de la ENV , que son más seguros genere un nuevo proceso de desprendimiento:

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 

o

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

sí, esto parece un poco menos hacky que perder el tiempo con RAILS_ENV –

+2

Para mí, invocar procesos adicionales de Rake parece mucho * más * hacky. –

+2

Es mejor que tener su tarea enredarse con el medio ambiente de una manera destructiva. Si lo haces de esta manera, puedes usarlo como una dependencia en otra tarea sin causar una catástrofe total. ¿Desea ejecutar una tarea de rake en modo de prueba? Ejecute la tarea en modo de prueba. Si intentas simular el modo de prueba, y probablemente lo cambien de nuevo a cualquier modo en el que estés realmente después, es incompleto. –

4

La mejor manera, por supuesto, es especificar el entorno desde la línea de comando cuando ejecuta la tarea de rake, pero si por algún motivo no es lo que quiere hacer, puede hacer esto:

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

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

Y eso debería hacer el truco.

+0

Es posible que sólo podrá requerir ' 'config/environment'' en lugar de volver a cargarla. – ealdent

+0

Qué hack, funciona como un campeón. –

+0

parece estar trabajando para la tarea de rake sin requerir o cargar ... –

6

el más limpio y solución más simple sería redefinir RAILS_ENV (no 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 

Durante el proceso de arranque de un RAILS_ENV aplicación Rails se inicializa como sigue

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

El resto del código Rails utiliza RAILS_ENV directamente.

Sin embargo, como Michael ha señalado en un comentario a su respuesta, cambiar RAILS_ENV sobre la marcha puede ser riesgoso. Otro enfoque sería cambiar la conexión de base de datos, esta solución es, de hecho, el valor por defecto utilizado por db:test tareas

ActiveRecord::Base.establish_connection(:test) 
17

En Rails 3, que tendrá que utilizar

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

en lugar de

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

Otra opción es verificar el env y rechazar continuar:

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

o pregunte si realmente quieren seguir:

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

Hay algo de código extraño en 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 

Siempre añade test si env es development. Resolví el caso de querer hacer una tarea personalizada db:rebuild para development y test simultáneos ejecutando primero development y test en segundo lugar.Además, antes de ejecutar las tareas, llamo a mi método set_env que se asegura de establecer ActiveRecord::Tasks::DatabaseTasks.env, sin esto, las conexiones de la base de datos no parecen manejarse discretamente para entornos como se esperaba. Probé todos los otros tipos de desconexión, etc., pero esto funcionó sin más código.

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

Here is a gist of my full db.rake file with simultaneous multi-environment db:rebuild and db:truncate

+0

no funciona en rieles 4 hasta el momento –

+0

Ha estado trabajando para nosotros en rieles 4 desde que se introdujo y todavía funciona en la actualidad. – kross

+0

Gracias. Bien, voy a ver tu esencia ahora. –

Cuestiones relacionadas