Pregunta Cómo pasar argumentos de línea de comando a una tarea de rake


Tengo una tarea de rake que necesita insertar un valor en múltiples bases de datos.

Me gustaría pasar este valor a la tarea de rake desde la línea de comando, o desde otro tarea de rake

¿Cómo puedo hacer esto?


950
2018-05-05 16:27


origen


Respuestas:


las opciones y las 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: variable task es el objeto de la tarea, no es muy útil a menos que sepa / se preocupe por las partes internas de Rake.

NOTA DE LOS RIELES:

Si ejecuta la tarea desde los rieles, es mejor precargar el entorno agregando => [:environment] que es una forma de configurar dependiente Tareas.

  task :work, [:option, :foo, :bar] => [:environment] do |task, args|
    puts "work", args
  end

229
2018-04-07 21:56



Puede especificar argumentos formales en rake agregando argumentos de símbolos 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 comando:

> rake my_task [1,2]
Args fueron: {: arg1 => "1",: arg2 => "2"}

> rake "my_task [1, 2]"
Args fueron: {: arg1 => "1",: arg2 => "2"}

> rake invoke_my_task
Args fueron: {: arg1 => "1",: arg2 => "2"}

> rake invoke_my_task_2
Args fueron: {: arg1 => 3,: arg2 => 4}

> rake con_prerequisito [5,6]
Args were: {: arg1 => "5",: arg2 => "6"}

> rake with_defaults
Args con los valores predeterminados eran: {: arg1 =>: default_1,: arg2 =>: default_2}

> rake with_defaults ['x', 'y']
Args con los valores predeterminados eran: {: arg1 => "x",: arg2 => "y"}

Como se demostró en el segundo ejemplo, si desea usar espacios, las comillas alrededor del nombre del objetivo son necesarias para evitar que el shell separe los argumentos en el espacio.

Mirando el código en rake.rb, parece que el rake no analiza cadenas de tareas para extraer argumentos de prerrequisitos, por lo que no se puede hacer 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 dependiente de la tarea, como en :invoke_my_task y :invoke_my_task_2.

Tenga en cuenta que algunos shells (como zsh) requieren que escapa de los corchetes: rake my_task\['arg1'\]


1081
2018-05-05 16:45



Además de responder por kch (no encontré cómo dejar un comentario sobre eso, lo siento):

No tiene que especificar variables como ENV variables antes de la rake mando. Puedes simplemente configurarlos como parámetros de línea de comando habituales como ese:

rake mytask var=foo

y acceda a los de su archivo rake como variables ENV como las siguientes:

p ENV['var'] # => "foo"

287
2018-02-19 11:05



Si desea pasar argumentos con nombre (por ejemplo, con estándar OptionParser) podrías usar algo como esto:

$ rake user:create -- --user test@example.com --pass 123

nota la --, eso es necesario para eludir los argumentos de Rake estándar. Debería funcionar con Rake 0.9.x, <= 10.3.x.

Newer Rake ha cambiado su análisis de --, y ahora debes asegurarte de que no se pase al OptionParser#parse método, 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 se interpretarán como tarea de Rake.

También el atajo para argumentos debería funcionar:

 rake user:create -- -u test@example.com -p 123

Cuando las secuencias de comandos de rake se ven así, tal vez es hora de buscar otra herramienta que permita esto recién salido de la caja.


94
2017-10-19 13:09



Encontré 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 rake es la siguiente:

desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
  #interesting things
end

Para pasar argumentos, haz tres cosas:

  1. Agregue los nombres de los argumentos después del nombre de la tarea, separados por comas.
  2. Coloque las dependencias al final usando: needs => [...]
  3. Place | t, args | después del do. (t es el objeto para 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ásale 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 pasar sus 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 forma 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

56
2018-05-05 16:51



Otra opción comúnmente utilizada es pasar variables de entorno. En tu código, los lees a través de ENV['VAR'], y puede pasarlos justo antes del rake comando, como

$ VAR=foo rake mytask

30
2018-05-05 16:53



De hecho, @Nick Desjardins respondió perfecto. Pero solo para la educación: puedes usar el enfoque sucio: usar ENV argumento

task :my_task do
  myvar = ENV['myvar']
  puts "myvar: #{myvar}"
end 

rake my_task myvar=10
#=> myvar: 10

30
2018-02-28 20:06



No pude resolver 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/']

24
2017-11-29 19:38