J'ai une tâche de rake qui doit insérer une valeur dans plusieurs bases de données.
J'aimerais transmettre cette valeur à la tâche rake à partir de la ligne de commande ou de autre tâche rake.
Comment puis-je faire ceci?
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
Ensuite
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 soins internes de Rake.
Rails NOTE:
Si vous exécutez la tâche à partir de Rails, il est préférable de précharger l'environnement en ajoutant
=> [:environment]
, qui permet de configurer les tâches dependantes.
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
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] Les args étaient: {: arg1 => "1",: arg2 => "2"} > rake "mon_task [1, 2]" Args étaient: {: arg1 => "1",: arg2 => "2"} > Rake invoke_my_task Args était: {: arg1 => "1",: arg2 = > "2"} > Rake invoke_my_task_2 Les args étaient: {: arg1 => 3,: arg2 => 4} > Rake avec_prerequisite [5,6] Les args étaient: {: arg1 => "5",: arg2 => "6"} > Rake with_defaults Les args avec des valeurs par défaut étaient: {: arg1 =>: default_1,: arg2 =>: default_2} > rake with_defaults ['x', 'y'] Les arguments par défaut étaient les suivants: {: arg1 => "x",: arg2 => "y"}
Comme illustré dans le deuxième exemple, si vous souhaitez utiliser des espaces, les guillemets autour du nom de la cible sont nécessaires pour empêcher le shell de fractionner les arguments au niveau 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. Vous ne pouvez donc 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 aux 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 variables ENV
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 voulez passer des arguments nommés (par exemple avec la variable standard OptionParser
), vous pouvez utiliser quelque chose comme ceci:
$ rake user:create -- --user [email protected] --pass 123
notez le --
, nécessaire pour ignorer les arguments standard de Rake. Devrait fonctionner avec Rake 0.9.x , <= 10.3.x .
Newer Rake a changé son analyse de --
, et vous devez maintenant vous assurer que cela 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 assurera que les arguments supplémentaires ne seront pas interprétés comme une tâche Rake.
De plus, le raccourci pour les arguments devrait fonctionner:
rake user:create -- -u [email protected] -p 123
Quand 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: 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:
Pour accéder aux arguments dans le 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]
va sortir
Hello
Hello
Hello
Hello
et si vous voulez appeler cette tâche depuis 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
va sortir
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: en utilisant l'argument ENV
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:
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/']
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? (Nan!)
Rake interprète arg1
et arg2
en tant que 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!
Disclaimer : Je voulais pouvoir faire cela dans un assez petit projet animalier. Non destiné à une utilisation "réelle" car vous perdez la possibilité de chaîner des tâches ratissées (c'est-à-dire rake task1 task2 task3
) L'OMI n'en vaut pas la peine. Il suffit d'utiliser le rake task[arg1,arg2]
laid.
J'utilise un argument Ruby régulier dans le fichier rake:
DB = ARGV[1]
ensuite, je décompose les tâches de rake au bas du fichier (car rake cherchera 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 var = foo ENV var et que la tâche propose des solutions [blah, blah2].
le stub est un peu jenky, mais pas trop mal si vous avez juste 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, la nouvelle version de Rails présente une petite technicité
Cela fonctionnera avec rake "namespace: taskname ['argument1']"
Notez les guillemets inversés dans l'exécution de la tâche à partir de la ligne de commande.
J'aime la syntaxe "querystring" pour le passage d'arguments, en particulier lorsqu'il y a beaucoup d'arguments à transmettre.
Exemple:
rake "mytask[width=10&height=20]"
La "chaîne de requête" étant:
width=10&height=20
Attention: notez que la syntaxe est rake "mytask[foo=bar]"
et NOTrake mytask["foo=bar"]
Lorsque analysé dans la tâche de rake en utilisant Rack::Utils.parse_nested_query
, nous obtenons une Hash
:
=> {"width"=>"10", "height"=>"20"}
(La chose intéressante est que vous pouvez passer des hachages et des tableaux, plus bas)
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 étendu 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, 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
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 build) lors de la transmission des arguments. J'aimerais 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 est disponible à l'adresse suivante: 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
Invoquer comme ça
bin/rake "task_name[value 1]" # entire argument string should be quoted
Si vous ne voulez pas vous soucier de savoir quelle est la position de l'argument et que vous voulez faire quelque chose comme un hachage d'argument Ruby Vous pouvez utiliser un seul argument pour passer 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 un style d'arguments traditionnel:
rake task arg1 arg2
Et ensuite utiliser:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Ajoutez 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