Ho un'attività di rake che deve inserire un valore in più database.
Vorrei passare questo valore nell'attività rake dalla riga di comando o da un'altra attività rake.
Come posso fare questo?
Ho un'attività di rake che deve inserire un valore in più database.
Vorrei passare questo valore nell'attività rake dalla riga di comando o da un'altra attività rake.
Come posso fare questo?
Risposte:
le opzioni e le dipendenze devono trovarsi all'interno di array:
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
Poi
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: variabile
task
è l'oggetto dell'attività, non molto utile se non si conosce / si preoccupa degli interni di Rake.
NOTA BINARIO:
Se si esegue l'attività da binari, è meglio precaricare l'ambiente aggiungendo
=> [:environment]
quale è un modo per impostare attività dipendenti .
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
rake thing:work[1, 2, 3]
poiché non funzionerà e otterrai un erroreDon't know how to build task
rake thing:work'[1,2,3]'
rake thing:work\[1,2,3\]
o questorake 'thing:work[1,2,3]'
:environment
simbolo dalla tua attività. le applicazioni rotaie hanno un compito: ambiente ...
t
significa task
, perché non usare semplicemente task
come nome param?
È possibile specificare argomenti formali nel rake aggiungendo argomenti simbolo alla chiamata attività. Per esempio:
require 'rake'
task :my_task, [:arg1, :arg2] do |t, args|
puts "Args were: #{args} of class #{args.class}"
puts "arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}"
puts "arg2 was: '#{args[:arg2]}' of class #{args[:arg2].class}"
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
Quindi, dalla riga di comando:
> rake my_task [1, false] Gli argomenti erano: {: arg1 => "1",: arg2 => "false"} della classe Rake :: TaskArguments arg1 era: '1' della classe String arg2 era: 'false' della classe String > rake "my_task [1, 2]" Gli argomenti erano: {: arg1 => "1",: arg2 => "2"} > rake invoke_my_task Gli argomenti erano: {: arg1 => "1",: arg2 => "2"} > rake invoke_my_task_2 Gli argomenti erano: {: arg1 => 3,: arg2 => 4} > rake with_prerequisite [5,6] Gli argomenti erano: {: arg1 => "5",: arg2 => "6"} > rake with_defaults Gli argomenti con valori predefiniti erano: {: arg1 =>: default_1,: arg2 =>: default_2} > rake with_defaults ['x', 'y'] Gli argomenti con valori predefiniti erano: {: arg1 => "x",: arg2 => "y"}
Come dimostrato nel secondo esempio, se si desidera utilizzare gli spazi, le virgolette attorno al nome di destinazione sono necessarie per impedire alla shell di dividere gli argomenti nello spazio.
Guardando il codice in rake.rb , sembra che rake non analizzi le stringhe di attività per estrarre argomenti per i prerequisiti, quindi non puoi farlo task :t1 => "dep[1,2]"
. L'unico modo per specificare argomenti diversi per un prerequisito sarebbe invocarlo esplicitamente all'interno dell'azione dell'attività dipendente, come in :invoke_my_task
e :invoke_my_task_2
.
Nota che alcune shell (come zsh) richiedono di sfuggire alle parentesi: rake my_task\['arg1'\]
WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
zsh: no matches found: ...
), quindi è necessario sfuggire le parentesi: rake my_task\['arg1'\]
. Da robots.thoughtbot.com/post/18129303042/…
Oltre a rispondere per kch (non ho trovato il modo di lasciare un commento, mi dispiace):
Non è necessario specificare le variabili come ENV
variabili prima del rake
comando. Puoi semplicemente impostarli come al solito parametri della riga di comando come questo:
rake mytask var=foo
e accedi a quelli dal tuo file rake come variabili ENV come queste:
p ENV['var'] # => "foo"
p
?
Se si desidera passare argomenti denominati (ad esempio con standard OptionParser
) è possibile utilizzare qualcosa del genere:
$ rake user:create -- --user test@example.com --pass 123
notare --
che è necessario per bypassare gli argomenti standard di Rake. Dovrebbe funzionare con Rake 0.9.x , <= 10.3.x .
Il rake più recente ha modificato l'analisi --
e ora è necessario assicurarsi che non sia passato al OptionParser#parse
metodo, ad esempio conparser.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
alla fine si assicurerà che gli argomenti extra non vengano interpretati come attività Rake.
Anche il collegamento per gli argomenti dovrebbe funzionare:
rake user:create -- -u test@example.com -p 123
Quando gli script rake sembrano così, forse è il momento di cercare un altro strumento che lo consenta immediatamente.
--option-names
. Il mio unico suggerimento sarebbe di usare exit
piuttosto che abort
come abort
ti lascerà con un codice di ritorno di 1 alla shell. Se l'attività di rake fa parte di uno script di livello superiore è più comune supporre che un'uscita diversa da zero sia un tipo di errore.
--
? Come passare rake
argomenti al compito reale o qualcosa del genere? Ti piace task :my_task, :*args do |t, args|
o qualcosa del genere?
{username}
serva. Dove è usato? Perché non c'è -u {username}
? Saluti
10.4.1
e ripristinato 10.4.2
. github.com/ruby/rake/commit/…
Ho trovato la risposta da questi due siti Web: Net Maniac e Aimred .
Per utilizzare questa tecnica devi avere una versione> 0.8 del rake
La normale descrizione dell'attività del rake è questa:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Per passare argomenti, fai tre cose:
Per accedere agli argomenti nello script, utilizzare 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
Per chiamare questa attività dalla riga di comando, passagli gli argomenti in [] s
rake task_name['Hello',4]
uscirà
Hello
Hello
Hello
Hello
e se si desidera chiamare questa attività da un'altra attività e passare argomenti, utilizzare invoke
task :caller do
puts 'In Caller'
Rake::Task[:task_name].invoke('hi',2)
end
quindi il comando
rake caller
uscirà
In Caller
hi
hi
Non ho trovato un modo per passare argomenti come parte di una dipendenza, poiché il seguente codice si rompe:
task :caller => :task_name['hi',2]' do
puts 'In Caller'
end
'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
Un'altra opzione comunemente usata è passare variabili d'ambiente. Nel tuo codice li leggi tramite ENV['VAR']
e puoi passarli subito prima del rake
comando, come
$ VAR=foo rake mytask
rake blah -- --these --go --to --a-program
(nota --
per dire a rake che i suoi switch sono terminati), vedi stackoverflow.com/questions/5086224/…
Non sono riuscito a capire come superare args e anche l'ambiente: fino a quando non ho capito:
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
E poi chiamo così:
rake db:export['foo, /tmp/']
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
puts args[:arg1]
end
rake task_name[hello, world]
Volevo solo essere in grado di eseguire:
$ rake some:task arg1 arg2
Semplice vero? (No!)
Rake interpreta arg1
e arg2
come attività e cerca di eseguirle. Quindi interrompiamo prima di farlo.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Prendi questo, parentesi!
Disclaimer : volevo essere in grado di farlo in un progetto piuttosto piccolo per animali domestici. Non destinato all'uso nel "mondo reale" poiché perdi la capacità di incatenare attività (ad es rake task1 task2 task3
.). IMO non ne vale la pena. Usa solo il brutto rake task[arg1,arg2]
.
_, arg1, arg2 = ARGV
perché il primo argomento era visto come il nome dell'attività di rake. Ma questo exit
è un trucco accurato.
rake task[arg1,arg2] && rake task2 && rake task3
Non sono sicuro che sia meno brutto di rake task[arg1,arg2] task2 task3
. Probabilmente meno efficiente però.
_, *args = ARGV
è perfetto per catturare tutti gli argomenti successivi! Grazie mille!
Uso un normale argomento ruby nel file rake:
DB = ARGV[1]
poi stub le attività di rake nella parte inferiore del file (poiché rake cercherà un'attività basata sul nome di quell'argomento).
task :database_name1
task :database_name2
riga di comando:
rake mytask db_name
questo mi sembra più pulito della var = foo ENV var e il compito args [blah, blah2] soluzioni.
lo stub è un po 'ingenuo, ma non troppo male se hai solo alcuni ambienti che sono una configurazione singola
dup
alla fine: db = ARGV [1] .dup
db = ARGV[1].dup unless ARGV[1].nil?
per evitare l'eccezione di duping zero.
I modi per passare l'argomento sono corretti nella risposta sopra. Tuttavia, per eseguire attività di rake con argomenti, è presente un piccolo tecnicismo nella versione più recente delle rotaie
Funzionerà con rake "namespace: taskname ['argomento1']"
Nota le virgolette invertite nell'esecuzione dell'attività dalla riga di comando.
Per passare argomenti all'attività predefinita, puoi fare qualcosa del genere. Ad esempio, dire "versione" è il tuo argomento:
task :default, [:version] => [:build]
task :build, :version do |t,args|
version = args[:version]
puts version ? "version is #{version}" : "no version passed"
end
Quindi puoi chiamarlo così:
$ 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
Tuttavia, non ho trovato un modo per evitare di specificare il nome dell'attività (impostazione predefinita o build) durante il passaggio degli argomenti. Mi piacerebbe sapere se qualcuno conosce un modo.
Mi piace la sintassi "querystring" per il passaggio degli argomenti, specialmente quando ci sono molti argomenti da passare.
Esempio:
rake "mytask[width=10&height=20]"
La "querystring" è:
width=10&height=20
Attenzione: nota che la sintassi è rake "mytask[foo=bar]"
e NON rake mytask["foo=bar"]
Quando analizzato all'interno dell'attività del rake usando Rack::Utils.parse_nested_query
, otteniamo un Hash
:
=> {"width"=>"10", "height"=>"20"}
(Il bello è che puoi passare hash e array, più sotto)
Ecco come raggiungere questo obiettivo:
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
Ecco un esempio più esteso che sto usando con Rails nella mia gemma 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]"
Analizzato come sopra, con una dipendenza dall'ambiente (per caricare l'ambiente 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
Fornisce quanto segue options
=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}
Se non puoi essere disturbato a ricordare quale posizione dell'argomento è per cosa e vuoi fare qualcosa come un hash dell'argomento rubino. È possibile utilizzare un argomento per passare una stringa e quindi regexare quella stringa in un hash delle opzioni.
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
E dalla riga di comando si ottiene.
$ 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
La maggior parte dei metodi sopra descritti non ha funzionato per me, forse sono deprecati nelle versioni più recenti. La guida aggiornata è disponibile qui: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks
un copia-e-incolla ans dalla guida è qui:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
Invocalo in questo modo
bin/rake "task_name[value 1]" # entire argument string should be quoted
Per eseguire attività di rake con lo stile degli argomenti tradizionali:
rake task arg1 arg2
E poi usa:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Aggiungi la seguente patch di 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
Mentre passa i parametri, è meglio l'opzione è un file di input, può essere un eccellente json o qualunque cosa tu abbia bisogno e da lì leggere la struttura dei dati e le variabili di cui hai bisogno tra cui il nome della variabile come è necessario. Per leggere un file può avere la seguente struttura.
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
{
"name_task": "I'm a task",
"user_id": 389,
"users_assigned": [389,672,524],
"task_id": 3
}
rake :name_task