rails - ruby rake task parameter




Comment passer des arguments de ligne de commande à une tâche de rake (12)

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

Je voudrais passer cette valeur dans la tâche rake à partir de la ligne de commande, ou d' une autre tâche de rake.

Comment puis-je faire ceci?


En fait, @Nick Desjardins a répondu parfait. Mais juste pour l'éducation: vous pouvez utiliser l'approche dirty: en utilisant l'argument ENV

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

rake my_task myvar=10
#=> myvar: 10

En passant les paramètres, il vaut mieux choisir un fichier d'entrée, cela peut-il être un excellent ou tout ce dont vous avez besoin et de là lire la structure de données et les variables dont vous avez besoin, y compris le nom de la variable. Pour 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 

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

Vous devez avoir une version> 0.8 de râteau pour utiliser cette technique

La description de la tâche rake normale 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 d'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. Place | 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 depuis la ligne de commande, passez-lui les arguments dans [] s

rake task_name['Hello',4]

sortira

Hello
Hello
Hello
Hello

et si vous voulez appeler cette tâche d'une autre tâche, et lui passer des arguments, utilisez invoke

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

alors la commande

rake caller

sortira

In Caller
hi
hi

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

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

J'aime la syntaxe "querystring" pour le passage des arguments, surtout quand il y a beaucoup d'arguments à passer.

Exemple:

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

Le "querystring" étant:

width=10&height=20

Attention: notez que la syntaxe est rake "mytask[foo=bar]" et pas rake mytask["foo=bar"]

Lorsque analysé dans la tâche de rake en utilisant Rack::Utils.parse_nested_query , nous obtenons un Hash :

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

(La chose cool est que vous pouvez passer des hachages et des tableaux, plus ci-dessous)

Voici comment y parvenir:

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 delayed_job_active_record_threaded que j'utilise avec Rails dans mon gem 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]"

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

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

Je ne pouvais pas comprendre comment passer args et aussi l'environnement: jusqu'à ce que j'ai travaillé sur ceci:

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 ça:

rake db:export['foo, /tmp/']

Je voulais juste pouvoir courir:

$ rake some:task arg1 arg2

Simple, non? (Nan!)

Rake interprète arg1 et arg2 comme des tâches et tente de les exécuter. Donc nous venons d'avorter avant.

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

    # your task...

    exit
  end
end

Prenez ça, les parenthèses!

Disclaimer : Je voulais être en mesure de le faire dans un joli petit projet pour animaux de compagnie. Non destiné à un usage "réel" puisque vous perdez la capacité de chaîner des tâches (ie rake task1 task2 task3 ). IMO ne vaut pas le coup. Utilisez simplement la rake task[arg1,arg2] laide rake task[arg1,arg2] .


Les moyens de passer l'argument sont corrects dans la réponse ci-dessus. Cependant, pour exécuter la tâche de rake avec des arguments, il y a une petite technicité impliquée dans la nouvelle version des rails

Cela fonctionnera avec rake "namespace: taskname ['argument1']"

Notez les citations inversées dans l'exécution de la tâche à partir de la ligne de commande.


Pour passer des arguments à la tâche par défaut, vous pouvez faire quelque chose comme ça. Par exemple, dites "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

Alors vous pouvez l'appeler comme ça:

$ 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é un moyen d'éviter de spécifier le nom de la tâche (default ou build) en passant des arguments. J'adorerais entendre si quelqu'un connaît un moyen.


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

$ rake user:create -- --user [email protected] --pass 123

Notez le -- , c'est nécessaire pour contourner les arguments Rake standard. Devrait fonctionner avec Rake 0.9.x , <= 10.3.x.

Newer Rake a changé son analyse de -- , et maintenant vous devez vous assurer qu'il n'est pas passé à la méthode OptionParser#parse , par exemple avec 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 à la fin s'assurera que les arguments supplémentaires ne seront pas interprétés comme une tâche Rake.

Aussi le raccourci pour les arguments devrait fonctionner:

 rake user:create -- -u [email protected] -p 123

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


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

$ VAR=foo rake mytask

les options et les dépendances doivent être dans des tableaux:

namespace :thing do
  desc "it does a thing"
  task :work, [:option, :foo, :bar] => [:environment] do |t, args|
    puts "work", args
  end

  task :another, [:option, :foo, :bar] => [:environment] do |t, 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"}

NOTE: la variable t est courte pour la task . C'est l'objet de la tâche, pas très utile à moins que vous sachiez ce que vous faites.


desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end




command-line-arguments