Cómo pasar argumentos de línea de comandos a una tarea de 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 rake desde la línea de comandos, o desde otra tarea rake.
¿Cómo puedo hacer esto?
17 answers
Las opciones y dependencias deben estar dentro de los arrays:
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 task, no es muy útil a menos que sepa/se preocupe por los internos de Rake.
RAILS NOTA:
Si ejecuta la tarea desde rails, lo mejor es 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-11 19:22:00
Puede especificar argumentos formales en rake añadiendo argumentos de símbolo a la llamada a la tarea. Por ejemplo:
require 'rake'
task :my_task, [:arg1, :arg2] do |t, args|
puts "Args were: #{args}"
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 comandos:
> rake my_task[1,2] Args were: {:arg1=>"1", :arg2=>"2"} > rake "my_task[1, 2]" Args were: {:arg1=>"1", :arg2=>"2"} > rake invoke_my_task Args were: {:arg1=>"1", :arg2=>"2"} > rake invoke_my_task_2 Args were: {:arg1=>3, :arg2=>4} > rake with_prerequisite[5,6] Args were: {:arg1=>"5", :arg2=>"6"} > rake with_defaults Args with defaults were: {:arg1=>:default_1, :arg2=>:default_2} > rake with_defaults['x','y'] Args with defaults were: {:arg1=>"x", :arg2=>"y"}
Como se demostró en el segundo ejemplo, si desea usar espacios, las comillas alrededor del nombre de destino son necesarias para evitar que el shell divida los argumentos en el espacio.
Mirando el código en rake.rb , parece que rake no analiza cadenas de tareas para extraer argumentos para prerrequisitos, por lo que no puedes hacer task :t1 => "dep[1,2]"
. La única manera de especificar diferentes argumentos para un prerrequisito sería invocarlo explícitamente dentro de la acción de tarea dependiente, como en :invoke_my_task
y :invoke_my_task_2
.
Ten en cuenta que algunos shells (como zsh) requieren que escapes de los corchetes: rake my_task\['arg1'\]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-08 15:32:57
Además de la respuesta de kch (no encontré cómo dejar un comentario a eso, lo siento):
No es necesario especificar variables como ENV
variables antes del comando rake
. Simplemente puede configurarlos como parámetros de línea de comandos habituales así:
rake mytask var=foo
Y acceder a los de su archivo de rake como variables ENV como tales:
p ENV['var'] # => "foo"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-16 19:35:18
Si desea pasar argumentos con nombre (por ejemplo, con estándar OptionParser
) podría usar algo como esto:
$ rake user:create -- --user [email protected] --pass 123
Tenga en cuenta el --
, que es necesario para evitar los argumentos de Rake estándar. Debería funcionar con Rake 0.9.x, .
El Rake más nuevo ha cambiado su análisis de --
, y ahora debe asegurarse de que no se pase al método OptionParser#parse
, por ejemplo con parser.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 serán interpretado como tarea Rake.
También el atajo para los argumentos debería funcionar:
rake user:create -- -u [email protected] -p 123
Cuando los scripts de rake se ven así, tal vez sea hora de buscar otra herramienta que permita esto solo fuera de la caja.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-11 10:49:28
He encontrado la respuesta en estos dos sitios web: Net Maniacy Aimred.
Necesita tener una versión > 0.8 de rake para usar esta técnica
La descripción normal de la tarea rake es esta:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Para pasar argumentos, haga tres cosas: {[13]]}
- Agregue los nombres de los argumentos después del nombre de la tarea, separados por comas.
- Ponga las dependencias al final usando: needs = > [...]
- Lugar |t, args| después del do. (t es el objeto de esta tarea)
Para acceder a los argumentos del script, utilice 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 comandos, pásele los argumentos en [] s
rake task_name['Hello',4]
Producirá
Hello
Hello
Hello
Hello
Y si desea llamar a esta tarea desde otra tarea, y pasarle argumentos, use invoke
task :caller do
puts 'In Caller'
Rake::Task[:task_name].invoke('hi',2)
end
Entonces el comando
rake caller
Producirá
In Caller
hi
hi
No he encontrado una manera de pasar argumentos como parte de una dependencia, ya que el siguiente código descansos:
task :caller => :task_name['hi',2]' do
puts 'In Caller'
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 16:51:45
Otra opción comúnmente utilizada es pasar variables de entorno. En tu código los lees a través de ENV['VAR']
, y puedes pasarlos justo antes del comando rake
, como
$ VAR=foo rake mytask
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 16:53:13
En realidad @Nick Desjardins respondió perfecto. Pero solo para la educación: puede usar el enfoque sucio: usando ENV
argumento
task :my_task do
myvar = ENV['myvar']
puts "myvar: #{myvar}"
end
rake my_task myvar=10
#=> myvar: 10
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-28 20:06:33
No podía averiguar cómo pasar args y también el: entorno hasta que resolví esto:
namespace :db do
desc 'Export product data'
task :export, [:file_token, :file_path] => :environment do |t, args|
args.with_defaults(:file_token => "products", :file_path => "./lib/data/")
#do stuff [...]
end
end
Y luego llamo así:
rake db:export['foo, /tmp/']
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-29 19:38:18
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
puts args[:arg1]
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-16 07:36:27
Uso un argumento ruby regular en el archivo rake:
DB = ARGV[1]
Entonces extraigo las tareas de rake en la parte inferior del archivo (ya que rake buscará una tarea basada en ese nombre de argumento).
task :database_name1
task :database_name2
Línea de comandos:
rake mytask db_name
Esto me parece más limpio que las soluciones var=foo ENV var y task args[blah, blah2].
el stub es un poco jenky, pero no está tan mal si solo tiene unos pocos entornos que son una configuración de una sola vez
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-29 02:48:52
Solo quería ser capaz de ejecutar:
$ rake some:task arg1 arg2
Simple, ¿verdad? (¡No!)
Rake interpreta arg1
y arg2
como tareas, e intenta ejecutarlas. Así que abortamos antes de que lo haga.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Toma eso, paréntesis!
Disclaimer: Quería ser capaz de hacer esto en un proyecto mascota bastante pequeño. No está pensado para el uso en el" mundo real", ya que pierde la capacidad de encadenar tareas de rake (es decir, rake task1 task2 task3
). IMO no vale la pena. Solo usa el feo rake task[arg1,arg2]
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-17 22:20:57
Las formas de pasar el argumento son correctas en la respuesta anterior. Sin embargo, para ejecutar la tarea rake con argumentos, hay un pequeño tecnicismo involucrado en la versión más reciente de rails
Funcionará con rake " namespace: taskname ['argument1']"
Observe las comillas invertidas al ejecutar la tarea desde la línea de comandos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-05 07:21:16
Me gusta la sintaxis "querystring" para pasar argumentos, especialmente cuando hay muchos argumentos a pasar.
Ejemplo:
rake "mytask[width=10&height=20]"
El" querystring " es:
width=10&height=20
Advertencia: tenga en cuenta que la sintaxis es rake "mytask[foo=bar]"
y NO rake mytask["foo=bar"]
Cuando se analiza dentro de la tarea rake usando Rack::Utils.parse_nested_query
, obtenemos un Hash
:
=> {"width"=>"10", "height"=>"20"}
(Lo bueno es que puedes pasar hashes y matrices, más abajo)
Esto es cómo lograr esto:
require 'rack/utils'
task :mytask, :args_expr do |t,args|
args.with_defaults(:args_expr => "width=10&height=10")
options = Rack::Utils.parse_nested_query(args[:args_expr])
end
Aquí hay un ejemplo más extendido que estoy usando con Rails en mi gema delayed_job_active_record_threaded:
bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"
Analizado de la misma manera que el anterior, con una dependencia de entorno (para cargar el entorno Rails)
namespace :dj do
task :start, [ :args_expr ] => :environment do |t, args|
# defaults here...
options = Rack::Utils.parse_nested_query(args[:args_expr])
end
end
Da lo siguiente en options
=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-16 22:05:07
Para pasar argumentos a la tarea predeterminada, puede hacer algo como esto. Por ejemplo, digamos "versión" es su argumento:
task :default, [:version] => [:build]
task :build, :version do |t,args|
version = args[:version]
puts version ? "version is #{version}" : "no version passed"
end
Entonces puedes llamarlo así:
$ rake
no version passed
O
$ rake default[3.2.1]
version is 3.2.1
O
$ rake build[3.2.1]
version is 3.2.1
Sin embargo, no he encontrado una manera de evitar especificar el nombre de la tarea (por defecto o compilación) al pasar argumentos. Me encantaría saber si alguien sabe de una manera.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-20 19:03:37
La mayoría de los métodos descritos anteriormente no funcionaron para mí, tal vez estén obsoletos en las versiones más recientes. La guía actualizada se puede encontrar aquí: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks
Una copia y pega ans de la guía está aquí:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
Invócalo así
bin/rake "task_name[value 1]" # entire argument string should be quoted
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-03 01:15:17
Si no se molesta en recordar qué argumento es position para qué y desea hacer algo como un hash de argumento ruby. Puede usar un argumento para pasar una cadena y luego regex esa cadena en un hash de opciones.
namespace :dummy_data do
desc "Tests options hash like arguments"
task :test, [:options] => :environment do |t, args|
arg_options = args[:options] || '' # nil catch incase no options are provided
two_d_array = arg_options.scan(/\W*(\w*): (\w*)\W*/)
puts two_d_array.to_s + ' # options are regexed into a 2d array'
string_key_hash = two_d_array.to_h
puts string_key_hash.to_s + ' # options are in a hash with keys as strings'
options = two_d_array.map {|p| [p[0].to_sym, p[1]]}.to_h
puts options.to_s + ' # options are in a hash with symbols'
default_options = {users: '50', friends: '25', colour: 'red', name: 'tom'}
options = default_options.merge(options)
puts options.to_s + ' # default option values are merged into options'
end
end
Y en la línea de comandos se obtiene.
$ rake dummy_data:test["users: 100 friends: 50 colour: red"]
[["users", "100"], ["friends", "50"], ["colour", "red"]] # options are regexed into a 2d array
{"users"=>"100", "friends"=>"50", "colour"=>"red"} # options are in a hash with keys as strings
{:users=>"100", :friends=>"50", :colour=>"red"} # options are in a hash with symbols
{:users=>"100", :friends=>"50", :colour=>"red", :name=>"tom"} # default option values are merged into options
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-12 01:44:06
Al pasar parámetros, es mejor opción es un archivo de entrada, puede ser un excel, un json o lo que sea que necesite y desde allí leer la estructura de datos y las variables que necesita de eso incluyendo el nombre de la variable como es la necesidad. Para leer un archivo puede tener la siguiente estructura.
namespace :name_sapace_task do
desc "Description task...."
task :name_task => :environment do
data = ActiveSupport::JSON.decode(File.read(Rails.root+"public/file.json")) if defined?(data)
# and work whit yoour data, example is data["user_id"]
end
end
Ejemplo json
{
"name_task": "I'm a task",
"user_id": 389,
"users_assigned": [389,672,524],
"task_id": 3
}
Ejecución
rake :name_task
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-11 23:43:07