Cómo pasar argumentos de línea de comando a una tarea rake
Tengo una tarea de rake que necesita insertar un valor en varias bases de datos.
Me gustaría pasar este valor a la tarea de rake desde la línea de comando o desde otra tarea de rake.
¿Cómo puedo hacer esto?
Puede especificar argumentos formales en rake agregando argumentos de símbolos a la llamada de tarea. Por ejemplo:
require 'rake'
task :my_task, [:arg1, :arg2] do |t, args|
puts "Args were: #{args} of class #{args.class}"
puts "arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}"
puts "arg2 was: '#{args[:arg2]}' of class #{args[:arg2].class}"
end
task :invoke_my_task do
Rake.application.invoke_task("my_task[1, 2]")
end
# or if you prefer this syntax...
task :invoke_my_task_2 do
Rake::Task[:my_task].invoke(3, 4)
end
# a task with prerequisites passes its
# arguments to it prerequisites
task :with_prerequisite, [:arg1, :arg2] => :my_task #<- name of prerequisite task
# to specify default values,
# we take advantage of args being a Rake::TaskArguments object
task :with_defaults, :arg1, :arg2 do |t, args|
args.with_defaults(:arg1 => :default_1, :arg2 => :default_2)
puts "Args with defaults were: #{args}"
end
Luego, desde la línea de comando:
> rastrillar my_task[1,false] Los argumentos fueron: {:arg1=>"1", :arg2=>"false"} de la clase Rake::TaskArguments arg1 era: '1' de la clase String arg2 era: 'falso' de la clase String > rastrillo "my_task[1, 2]" Los argumentos fueron: {:arg1=>"1", :arg2=>"2"} > rastrillar invoke_my_task Los argumentos fueron: {:arg1=>"1", :arg2=>"2"} > rastrillo invoke_my_task_2 Los argumentos fueron: {:arg1=>3, :arg2=>4} > rastrillo con_prerrequisito[5,6] Los argumentos fueron: {:arg1=>"5", :arg2=>"6"} > rastrillo con_defaults Los argumentos con valores predeterminados eran: {:arg1=>:default_1, :arg2=>:default_2} > rastrillo con_defaults['x','y'] Los argumentos con valores predeterminados eran: {:arg1=>"x", :arg2=>"y"}
Como se demuestra en el segundo ejemplo, si desea utilizar espacios, las comillas alrededor del nombre del objetivo son necesarias para evitar que el shell divida los argumentos en el espacio.
Al observar el código en rake.rb , parece que rake no analiza las cadenas de tareas para extraer argumentos para los requisitos previos, por lo que no puede hacerlo task :t1 => "dep[1,2]"
. La única forma de especificar diferentes argumentos para un requisito previo sería invocarlo explícitamente dentro de la acción de la tarea dependiente, como en :invoke_my_task
y :invoke_my_task_2
.
Tenga en cuenta que algunos shells (como zsh) requieren que escape los corchetes:rake my_task\['arg1'\]
Las opciones y dependencias deben estar dentro de matrices:
namespace :thing do
desc "it does a thing"
task :work, [:option, :foo, :bar] do |task, args|
puts "work", args
end
task :another, [:option, :foo, :bar] do |task, args|
puts "another #{args}"
Rake::Task["thing:work"].invoke(args[:option], args[:foo], args[:bar])
# or splat the args
# Rake::Task["thing:work"].invoke(*args)
end
end
Entonces
rake thing:work[1,2,3]
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}
rake thing:another[1,2,3]
=> another {:option=>"1", :foo=>"2", :bar=>"3"}
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}
NOTA: la variable
task
es el objeto de la tarea, no es muy útil a menos que conozca o se interese por los aspectos internos de Rake.
NOTA DE RIELES:
Si ejecuta la tarea desde Rails, es mejor precargar el entorno agregando,
=> [:environment]
que es una forma de configurar tareas dependientes .
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
Además de responder por kch (no encontré como dejar un comentario a eso, lo siento):
No es necesario especificar variables como ENV
variables antes del rake
comando. Puedes configurarlos como parámetros habituales de línea de comando así:
rake mytask var=foo
y acceda a aquellos desde su archivo rake como variables ENV como estas:
p ENV['var'] # => "foo"
Si desea pasar argumentos con nombre (por ejemplo, con estándar OptionParser
), puede usar algo como esto:
$ rake user:create -- --user test@example.com --pass 123
tenga en cuenta --
que es necesario para omitir los argumentos estándar de Rake. Debería funcionar con Rake 0.9.x , <= 10.3.x.
El nuevo Rake ha cambiado su análisis --
y ahora debe asegurarse de que no se pase al OptionParser#parse
método, por ejemplo conparser.parse!(ARGV[2..-1])
require 'rake'
require 'optparse'
# Rake task for creating an account
namespace :user do |args|
desc 'Creates user account with given credentials: rake user:create'
# environment is required to have access to Rails models
task :create do
options = {}
OptionParser.new(args) do |opts|
opts.banner = "Usage: rake user:create [options]"
opts.on("-u", "--user {username}","User's email address", String) do |user|
options[:user] = user
end
opts.on("-p", "--pass {password}","User's password", String) do |pass|
options[:pass] = pass
end
end.parse!
puts "creating user account..."
u = Hash.new
u[:email] = options[:user]
u[:password] = options[:pass]
# with some DB layer like ActiveRecord:
# user = User.new(u); user.save!
puts "user: " + u.to_s
puts "account created."
exit 0
end
end
exit
al final se asegurará de que los argumentos adicionales no se interpreten como una tarea de Rake.
También debería funcionar el atajo para argumentos:
rake user:create -- -u test@example.com -p 123
Cuando los scripts de rake se ven así, tal vez sea el momento de buscar otra herramienta que permita esto de forma inmediata.
Encontré la respuesta en estos dos sitios web: Net Maniac y Aimred .
Necesitas tener la versión > 0.8 de rake para usar esta técnica
La descripción normal de la tarea de rake es la siguiente:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Para pasar argumentos, haga tres cosas:
- Agregue los nombres de los argumentos después del nombre de la tarea, separados por comas.
- Coloque las dependencias al final usando :needs => [...]
- Coloque |t, argumentos| después del hacer. (t es el objeto de esta tarea)
Para acceder a los argumentos en el script, use args.arg_name
desc 'Takes arguments task'
task :task_name, :display_value, :display_times, :needs => [:depends_on_taskA, :depends_on_taskB] do |t, args|
args.display_times.to_i.times do
puts args.display_value
end
end
Para llamar a esta tarea desde la línea de comando, pásele los argumentos en []s
rake task_name['Hello',4]
saldrá
Hello
Hello
Hello
Hello
y si desea llamar a esta tarea desde otra tarea y pasarle argumentos, use invocar
task :caller do
puts 'In Caller'
Rake::Task[:task_name].invoke('hi',2)
end
entonces el comando
rake caller
saldrá
In Caller
hi
hi
No he encontrado una manera de pasar argumentos como parte de una dependencia, ya que el siguiente código falla:
task :caller => :task_name['hi',2]' do
puts 'In Caller'
end