Tengo una tarea de rastrillo que necesita insertar un valor en múltiples bases de datos.
Me gustaría pasar este valor a la tarea de rastrillo desde la línea de comando, o desde otra tarea de rastrillo.
¿Cómo puedo hacer esto?
Tengo una tarea de rastrillo que necesita insertar un valor en múltiples bases de datos.
Me gustaría pasar este valor a la tarea de rastrillo desde la línea de comando, o desde otra tarea de rastrillo.
¿Cómo puedo hacer esto?
Respuestas:
Las opciones y dependencias deben estar dentro de las 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 / se preocupe por las partes internas de Rake.
NOTA DE RAILS:
Si ejecuta la tarea desde rieles, es mejor precargar el entorno agregando
=> [:environment]
cuál es una forma de configurar tareas dependientes .
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
rake thing:work[1, 2, 3]
ya que no funcionará y obtendrás un errorDon't know how to build task
rake thing:work'[1,2,3]'
rake thing:work\[1,2,3\]
o estorake 'thing:work[1,2,3]'
:environment
símbolo de su tarea. aplicaciones de rieles tienen una: tarea de entorno ...
t
medios task
, ¿por qué no usar simplemente task
como el param name?
Puede especificar argumentos formales en rake agregando argumentos de símbolo 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 mi_tarea [1, falso] 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"} > rastrillo invoke_my_task Los argumentos fueron: {: arg1 => "1",: arg2 => "2"} > rastrillo invoke_my_task_2 Los argumentos fueron: {: arg1 => 3,: arg2 => 4} > rastrillo con requisito previo [5,6] Los argumentos fueron: {: arg1 => "5",: arg2 => "6"} > rake with_defaults Los argumentos con valores predeterminados fueron: {: arg1 =>: default_1,: arg2 =>: default_2} > rake with_defaults ['x', 'y'] Los argumentos con valores predeterminados fueron: {: 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.
Al observar el código en rake.rb , parece que rake no analiza las cadenas de tareas para extraer argumentos de 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 de los corchetes: rake my_task\['arg1'\]
WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
zsh: no matches found: ...
), por lo que necesita para escapar de los soportes: rake my_task\['arg1'\]
. De robots.thoughtbot.com/post/18129303042/…
Además de responder por kch (no encontré cómo dejar un comentario a eso, lo siento):
No tiene que especificar variables como ENV
variables antes del rake
comando. Simplemente puede configurarlos como parámetros de línea de comandos habituales como ese:
rake mytask var=foo
y acceda a los de su archivo rake como variables ENV como tales:
p ENV['var'] # => "foo"
p
?
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 pasar por alto los argumentos estándar de Rake. En caso de trabajar con el rastrillo 0.9.x , <= 10.3.x .
Newer Rake ha cambiado su análisis --
, y ahora debe asegurarse de que no se haya pasado 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 tarea Rake.
También el atajo para argumentos debería funcionar:
rake user:create -- -u test@example.com -p 123
Cuando los scripts de rastrillo se ven así, tal vez sea hora de buscar otra herramienta que permita esto de manera inmediata.
--option-names
. Mi única sugerencia sería usar en exit
lugar de abort
como abort
lo dejará con un código de retorno de 1 al shell. Si la tarea de rake es parte de un script de nivel superior, es más común asumir que una salida distinta de cero es algún tipo de error.
--
? ¿Como pasar rake
argumentos a la tarea real o algo así? ¿Me gusta task :my_task, :*args do |t, args|
o algo?
{username}
está aquí. Donde se usa ¿Por qué no está allí -u {username}
? Saludos
He encontrado la respuesta de estos dos sitios web: Net Maniac y Aimred .
Necesitas tener una versión> 0.8 de rastrillo para usar esta técnica
La descripción normal de la tarea de rastrillo 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:
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 invoke
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 se rompe:
task :caller => :task_name['hi',2]' do
puts 'In Caller'
end
'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
Otra opción comúnmente utilizada es pasar variables de entorno. En su código, los lee ENV['VAR']
y puede pasarlos justo antes del rake
comando, como
$ VAR=foo rake mytask
rake blah -- --these --go --to --a-program
(observe el --
rastrillo para decirle que sus interruptores han terminado), consulte stackoverflow.com/questions/5086224/…
No pude entender 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/']
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
puts args[:arg1]
end
rake task_name[hello, world]
Solo quería poder ejecutar:
$ rake some:task arg1 arg2
Simple, ¿verdad? (¡No!)
Rake interpreta arg1
y arg2
como tareas, e intenta ejecutarlas. Entonces 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!
Descargo de responsabilidad : quería poder hacer esto en un proyecto de mascotas bastante pequeño. No está destinado al uso en el "mundo real" ya que pierde la capacidad de encadenar tareas de rastrillo (es decir rake task1 task2 task3
). OMI no vale la pena. Solo usa lo feo rake task[arg1,arg2]
.
_, arg1, arg2 = ARGV
ya que el primer argumento era el nombre de la tarea de rastrillo. Pero ese exit
es un buen truco.
rake task[arg1,arg2] && rake task2 && rake task3
No estoy seguro si eso es menos feo que rake task[arg1,arg2] task2 task3
. Probablemente menos eficiente sin embargo.
_, *args = ARGV
¡Es perfecto para capturar todos los argumentos posteriores! ¡Montones de gracias!
Utilizo un argumento ruby regular en el archivo rastrillo:
DB = ARGV[1]
luego apago las tareas de rastrillo en la parte inferior del archivo (ya que el rastrillo buscará una tarea basada en ese nombre de argumento).
task :database_name1
task :database_name2
línea de comando:
rake mytask db_name
esto me parece más limpio que el var = foo ENV var y la tarea argumenta [bla, blah2] soluciones.
el trozo es un poco jenky, pero no está mal si solo tienes algunos entornos que son una configuración única
dup
al final: db = ARGV [1] .dup
db = ARGV[1].dup unless ARGV[1].nil?
para evitar la excepción de duplicar un cero.
Las formas de pasar el argumento son correctas en la respuesta anterior. Sin embargo, para ejecutar la tarea de rake con argumentos, hay un pequeño tecnicismo involucrado en la versión más nueva de rails
Funcionará con rake "espacio de nombres: nombre de tarea ['argumento1']"
Tenga en cuenta las comillas invertidas al ejecutar la tarea desde la línea de comandos.
Para pasar argumentos a la tarea predeterminada, puede hacer algo como esto. Por ejemplo, decir "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 (predeterminado o compilación) al pasar argumentos. Me encantaría saber si alguien sabe de alguna manera.
Me gusta la sintaxis de "cadena de consulta" para pasar argumentos, especialmente cuando hay muchos argumentos para pasar.
Ejemplo:
rake "mytask[width=10&height=20]"
La "cadena de consulta" 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 de rastrillo usando Rack::Utils.parse_nested_query
, obtenemos un Hash
:
=> {"width"=>"10", "height"=>"20"}
(Lo bueno es que puedes pasar hash y matrices, más abajo)
Así es como 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 extenso que estoy usando con Rails en mi gema retrayed_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 arriba, con una dependencia del 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"}}
Si no puede molestarse en recordar qué posición de argumento es para qué y desea hacer algo como un hash de argumento de rubí. Puede usar un argumento para pasar una cadena y luego volver a expresar 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 comando que obtienes.
$ 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
La mayoría de los métodos descritos anteriormente no funcionaron para mí, tal vez están en desuso en las versiones más recientes. La guía actualizada se puede encontrar aquí: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks
Copie y pegue la respuesta de la guía aquí:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
Invocarlo así
bin/rake "task_name[value 1]" # entire argument string should be quoted
Para ejecutar tareas de rastrillo con estilo de argumentos tradicionales:
rake task arg1 arg2
Y luego usa:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Agregue el siguiente parche de gema de rastrillo:
Rake::Application.class_eval do
alias origin_top_level top_level
def top_level
@top_level_tasks = [top_level_tasks.join(' ')]
origin_top_level
end
def parse_task_string(string) # :nodoc:
parts = string.split ' '
return parts.shift, parts
end
end
Rake::Task.class_eval do
def invoke(*args)
invoke_with_call_chain(args, Rake::InvocationChain::EMPTY)
end
end
Al pasar los parámetros, es mejor que la opción sea un archivo de entrada, puede ser un excel a json o lo que necesite y, a partir de ahí, lea la estructura de datos y las variables que necesita, incluido el nombre de la variable según sea necesario. 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
{
"name_task": "I'm a task",
"user_id": 389,
"users_assigned": [389,672,524],
"task_id": 3
}
rake :name_task