Pregunta

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

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

¿Cómo puedo hacer esto?

¿Fue útil?

Solución

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] que es una forma de configurar tareas dependientes .

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

Otros consejos

Puede especificar argumentos formales en el rastrillo por la adición de símbolo argumentos a la tarea de llamar.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

Entonces, 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 muestra en el segundo ejemplo, si desea utilizar los espacios, las comillas alrededor del nombre de destino son necesarios para mantener la concha de la división de seguridad de los argumentos en el espacio.

Mirando el código en de rake.rb, parece que el rake no analiza tarea cadenas para extraer argumentos para requisitos previos, por lo que no puede hacer task :t1 => "dep[1,2]".La única manera de especificar diferentes argumentos para un requisito previo sería invoca explícitamente dentro de la dependiente de la acción de la tarea, como en :invoke_my_task y :invoke_my_task_2.

Tenga en cuenta que algunas de las conchas (como zsh) requieren que escapar de los corchetes: rake my_task\['arg1'\]

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 comando rake. Simplemente puede configurarlos como parámetros de línea de comandos habituales como ese:

rake mytask var=foo

y acceda a ellos desde su archivo rake como variables ENV como tales:

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

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

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

tenga en cuenta --, eso es necesario para omitir los argumentos estándar de Rake. Debería funcionar con Rake 0.9.x , & Lt; = 10.3.x .

Newer Rake ha cambiado su análisis de OptionParser#parse, y ahora debe asegurarse de que no se pasa al método parser.parse!(ARGV[2..-1]), por ejemplo con exit

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

<=> 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 forma inmediata.

He encontrado la respuesta de estos dos sitios web: Net Maniac y Aimred .

Necesita tener la versión > 0.8 de rastrillo para usar esta técnica

La descripción normal de la tarea de rastrillo es esta:

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

Para pasar argumentos, haga tres cosas:

  1. Agregue los nombres de los argumentos después del nombre de la tarea, separados por comas.
  2. Ponga las dependencias al final usando: needs = > [...]
  3. Lugar | t, args | después del do. (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]

generará

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

luego el comando

rake caller

generará

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

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

$ VAR=foo rake mytask

En realidad, @Nick Desjardins respondió perfecto. Pero solo para la educación: puede usar un enfoque sucio: usar ENV argumento

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

rake my_task myvar=10
#=> myvar: 10

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

Yo sólo quería ser capaz de ejecutar:

$ rake some:task arg1 arg2

Sencillo, ¿verdad?(No!)

Rake interpreta arg1 y arg2 como tareas, y trata de ejecutar.Así que acaba de abortar antes de que suceda.

namespace :some do
  task task: :environment do
    arg1, arg2 = ARGV

    # your task...

    exit
  end
end

Tomar que, entre paréntesis!

Descargo de responsabilidad:Yo quería ser capaz de hacer esto en una hermosa pequeña mascota del proyecto.No destinados al "mundo real" de uso ya que se pierde la capacidad de de la cadena de tareas rake (es decir, rake task1 task2 task3).IMO no vale la pena.Sólo uso el feo rake task[arg1,arg2].

Yo uso regular de ruby argumento en el rastrillo de archivo:

DB = ARGV[1]

entonces yo punta de el rastrillo de tareas en la parte inferior del archivo (desde rake buscará una tarea basada en el argumento nombre).

task :database_name1
task :database_name2

línea de comandos:

rake mytask db_name

esto se siente más limpio para mí que el var=foo ENV var y la tarea args[bla, blah2] las soluciones.
la punta es un poco jenky, pero no demasiado malo si sólo tienes un par de ambientes que son de un solo tiempo de instalación

Las formas de pasar el argumento son correctas en la respuesta anterior. Sin embargo, para ejecutar la tarea de rastrillo con argumentos, hay un pequeño tecnicismo involucrado en la versión más nueva de los rieles

Funcionará con rake " namespace: taskname ['argumento1'] "

Tenga en cuenta las comillas invertidas al ejecutar la tarea desde la línea de comandos.

Me gusta la "cadena" de la sintaxis de un argumento que pasa, especialmente cuando hay una gran cantidad de argumentos que se pasan.

Ejemplo:

rake "mytask[width=10&height=20]"

La "cadena ser":

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 rake el uso de Rack::Utils.parse_nested_query obtenemos una Hash:

=> {"width"=>"10", "height"=>"20"}

(Lo bueno es que se puede pasar de hashes y matrices, más abajo)

Esta es la manera de 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

He aquí una más extendida ejemplo que estoy usando con Rieles en mi delayed_job_active_record_threaded gema:

bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"

Se analiza de la misma forma que anteriormente, con un ambiente de dependencia (en orden de cargar el entorno de 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 el siguiente en options

=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}

Para pasar argumentos a la tarea predeterminada, puede hacer algo como esto. Por ejemplo, di " versión " es tu 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.

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-tareas

un ans de copiar y pegar 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

Invocarlo así

bin/rake "task_name[value 1]" # entire argument string should be quoted

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

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 sea 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

Ejemplo json

{
  "name_task": "I'm a task",
  "user_id": 389,
  "users_assigned": [389,672,524],
  "task_id": 3
}

Ejecución

rake :name_task 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top