Question

J'ai une tâche de rake qui doit insérer une valeur dans plusieurs bases de données.

J'aimerais transmettre cette valeur dans la tâche rake à partir de la ligne de commande ou de un autre tâche de râteau.

Comment puis-je faire ceci?

Était-ce utile?

La solution

les options et les dépendances doivent être à l'intérieur des tableaux:

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

Alors

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"}
  

REMARQUE: la variable task est l’objet de la tâche. Elle n’est pas très utile si vous ne connaissez pas les internautes de Rake.

NOTE SUR LES RAILS:

  

Si vous exécutez la tâche à partir de rails, il est préférable de précharger l'environnement en ajoutant => [:environment], ce qui permet de configurer les tâches dépendantes .

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

Autres conseils

Vous pouvez spécifier des arguments formels dans rake en ajoutant des arguments de symbole à l'appel de tâche. Par exemple:

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

Ensuite, à partir de la ligne de commande:

> 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"}

Comme indiqué dans le deuxième exemple, si vous souhaitez utiliser des espaces, les guillemets entourant le nom de la cible sont nécessaires pour empêcher le shell de séparer les arguments de l'espace.

En regardant le code dans rake.rb , il apparaît que rake n'analyse pas les chaînes de tâches pour extraire les arguments des conditions préalables. Par conséquent, vous ne pouvez pas utiliser task :t1 => "dep[1,2]". La seule façon de spécifier différents arguments pour un prérequis serait de l'invoquer explicitement dans l'action de tâche dépendante, comme dans :invoke_my_task et :invoke_my_task_2.

Notez que certains shells (comme zsh) vous obligent à échapper les crochets: rake my_task\['arg1'\]

En plus de répondre par kch (désolé, je n'ai pas trouvé comment commenter cela):

Il n'est pas nécessaire de spécifier des variables en tant que ENV variables avant la commande rake. Vous pouvez simplement les définir comme paramètres de ligne de commande habituels, comme ceci:

rake mytask var=foo

et accédez à ceux de votre fichier rake en tant que variables ENV telles que:

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

Si vous souhaitez passer des arguments nommés (par exemple avec la norme OptionParser), vous pouvez utiliser quelque chose comme ceci:

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

Notez le --, qui est nécessaire pour ignorer les arguments standard de Rake. Devrait fonctionner avec Rake 0.9.x , & Lt; = 10.3.x .

Newer Rake a modifié l'analyse de OptionParser#parse. Vous devez maintenant vous assurer qu'il n'est pas transmis à la méthode parser.parse!(ARGV[2..-1]), par exemple avec 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

<=> à la fin assurera que les arguments supplémentaires ne seront pas interprétés comme une tâche Rake.

Le raccourci pour les arguments devrait également fonctionner:

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

Lorsque les scripts de rake ressemblent à ceci, il est peut-être temps de chercher un autre outil qui permettrait de sortir de la boîte.

J'ai trouvé la réponse de ces deux sites Web: Net Maniac et Aimred .

Vous devez avoir la version > 0.8 de rake pour utiliser cette technique

La description normale de la tâche de rake est la suivante:

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

Pour passer des arguments, faites trois choses:

  1. Ajoutez les noms des arguments après le nom de la tâche, séparés par des virgules.
  2. Mettez les dépendances à la fin en utilisant: needs = > [...]
  3. Lieu | t, args | après le faire. (t est l'objet de cette tâche)

Pour accéder aux arguments du script, utilisez 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

Pour appeler cette tâche à partir de la ligne de commande, transmettez-lui les arguments dans [] s

rake task_name['Hello',4]

affichera

Hello
Hello
Hello
Hello

et si vous souhaitez appeler cette tâche à partir d'une autre tâche et lui transmettre des arguments, utilisez invoke

task :caller do
  puts 'In Caller'
  Rake::Task[:task_name].invoke('hi',2)
end

alors la commande

rake caller

affichera

In Caller
hi
hi

Je n'ai pas trouvé de moyen de passer des arguments dans le cadre d'une dépendance, car le code suivant se casse:

task :caller => :task_name['hi',2]' do
   puts 'In Caller'
end

Une autre option couramment utilisée consiste à transmettre des variables d’environnement. Dans votre code, vous les lisez via ENV['VAR'] et vous pouvez les transmettre juste avant la commande rake, comme

.
$ VAR=foo rake mytask

En fait, @Nick Desjardins a répondu parfaitement. Mais juste pour l’éducation: vous pouvez utiliser une approche sale: utiliser ENV argument

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

rake my_task myvar=10
#=> myvar: 10

Je n'arrivais pas à comprendre comment passer des arguments et l'environnement: jusqu'à ce que je sache ce qu'il en est:

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

Et puis j'appelle comme ceci:

rake db:export['foo, /tmp/']
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end

Je voulais juste pouvoir courir:

$ rake some:task arg1 arg2

Simple, non? (Nope!)

Rake interprète arg1 et arg2 comme des tâches et tente de les exécuter. Donc, nous avortons juste avant.

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

    # your task...

    exit
  end
end

Prenez ça, entre parenthèses!

Clause de non-responsabilité : je souhaitais pouvoir réaliser cela dans un assez petit projet pour animaux de compagnie. Non destiné au & Quot; monde réel & Quot; utilisation puisque vous perdez la possibilité de chaîner des tâches de ratissage (c.-à-d. rake task1 task2 task3). L'OMI n'en vaut pas la peine. Il suffit d’utiliser le laid rake task[arg1,arg2].

J'utilise un argument Ruby régulier dans le fichier rake :

DB = ARGV[1]

puis je supprime les tâches de rake au bas du fichier (puisque rake recherchera une tâche basée sur ce nom d'argument).

task :database_name1
task :database_name2

ligne de commande:

rake mytask db_name

cela me semble plus propre que les solutions var=foo ENV var et la tâche args[blah, blah2].
le stub est un peu saccadé, mais pas trop mal si vous n'avez que quelques environnements qui sont une configuration unique

Les manières de passer l'argument sont correctes dans la réponse ci-dessus. Cependant, pour exécuter une tâche rake avec des arguments, il existe une petite technicité dans la nouvelle version des rails

Cela fonctionnera avec rake " espace de nom: nom_tâche ['argument1'] "

Notez les guillemets inversés lors de l'exécution de la tâche à partir de la ligne de commande.

J'aime la " chaîne de requête & "; syntaxe de passage des arguments, surtout quand il y a beaucoup d’arguments à passer.

Exemple:

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

La " chaîne de requête & "; être:

width=10&height=20

Avertissement: , notez que la syntaxe est rake "mytask[foo=bar]" et NON rake mytask["foo=bar"]

Lors de l'analyse dans la tâche de rake avec Rack::Utils.parse_nested_query, nous obtenons un Hash:

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

(La chose intéressante est que vous pouvez passer des hachages et des tableaux, plus bas)

Voici comment procéder:

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

Voici un exemple plus complet que j'utilise avec Rails dans mon delay_job_active_record_threaded gem:

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

Analysé de la même manière que ci-dessus, avec une dépendance d'environnement (pour charger l'environnement 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

Donne ce qui suit dans options

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

Pour passer des arguments à la tâche par défaut, vous pouvez faire quelque chose comme ceci. Par exemple, disons " version " est votre argument:

task :default, [:version] => [:build]

task :build, :version do |t,args|
  version = args[:version]
  puts version ? "version is #{version}" : "no version passed"
end

Ensuite, vous pouvez l'appeler comme suit:

$ rake
no version passed

ou

$ rake default[3.2.1]
version is 3.2.1

ou

$ rake build[3.2.1]
version is 3.2.1

Cependant, je n'ai pas trouvé le moyen d'éviter de spécifier le nom de la tâche (par défaut ou construit) lors de la transmission d'arguments. J'adorerais entendre si quelqu'un connaît un moyen.

La plupart des méthodes décrites ci-dessus n'ont pas fonctionné pour moi. Elles sont peut-être obsolètes dans les versions les plus récentes. Le guide mis à jour se trouve ici: http: //guides.rubyonrails .org / command_line.html # custom-rake-tasks

un copier-coller du guide est ici:

task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
  # You can use args from here
end

Invoquez-le comme ceci

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

Si vous ne voulez pas être dérangé de vous rappeler quelle est la position de l’argument pour quoi et vous voulez faire quelque chose comme un hachage d’argument Ruby Vous pouvez utiliser un seul argument pour transmettre une chaîne, puis regexer cette chaîne dans un hachage d'options.

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

Et sur la ligne de commande, vous obtenez.

$ 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

Pour exécuter des tâches rake avec des arguments classiques, procédez comme suit:

rake task arg1 arg2

Et utilisez ensuite:

task :task do |_, args|
  puts "This is argument 1: #{args.first}"
end

Ajouter le patch suivant de rake gem:

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

Lorsqu’on passe des paramètres, il est préférable d’utiliser un fichier d’entrée. Cela peut être un excellent fichier json ou ce dont vous avez besoin. À partir de là, lisez la structure de données et les variables dont vous avez besoin, y compris le nom de la variable. Lire un fichier peut avoir la structure suivante:

  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

Exemple json

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

Exécution

rake :name_task 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top