Eu tenho uma tarefa de rake que precisa inserir um valor em vários bancos de dados.
Eu gostaria de passar esse valor para a tarefa rake na linha de comando ou de outra tarefa rake.
Como posso fazer isso?
Eu tenho uma tarefa de rake que precisa inserir um valor em vários bancos de dados.
Eu gostaria de passar esse valor para a tarefa rake na linha de comando ou de outra tarefa rake.
Como posso fazer isso?
Respostas:
opções e dependências precisam estar dentro de matrizes:
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
Então
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: variável
task
é o objeto da tarefa, não muito útil, a menos que você conheça / se preocupe com os recursos internos do Rake.
NOTA DOS TRILHOS:
Se estiver executando a tarefa a partir dos trilhos, é melhor pré-carregar o ambiente, adicionando
=> [:environment]
qual é a maneira de configurar tarefas dependentes .
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
rake thing:work[1, 2, 3]
como ele não vai funcionar e você terá um erroDon't know how to build task
rake thing:work'[1,2,3]'
rake thing:work\[1,2,3\]
ou estarake 'thing:work[1,2,3]'
:environment
símbolo da sua tarefa. trilhos aplicações têm um: tarefa ambiente ...
t
meios task
, por que não usar task
como o nome param?
Você pode especificar argumentos formais no rake adicionando argumentos de símbolo à chamada de tarefa. Por exemplo:
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
Em seguida, na linha de comando:
> rake my_task [1, falso] Os argumentos foram: {: arg1 => "1",: arg2 => "false"} da classe Rake :: TaskArguments arg1 era: '1' da classe String arg2 era: 'false' da classe String > rake "minha_task [1, 2]" Os argumentos foram: {: arg1 => "1",: arg2 => "2"} > rake invoke_my_task Os argumentos foram: {: arg1 => "1",: arg2 => "2"} > rake invoke_my_task_2 Os argumentos foram: {: arg1 => 3,: arg2 => 4} > rake com pré-requisito [5,6] Os argumentos foram: {: arg1 => "5",: arg2 => "6"} > rake with_defaults Os argumentos com padrões foram: {: arg1 =>: default_1,: arg2 =>: default_2} > rake with_defaults ['x', 'y'] Os argumentos com padrões foram: {: arg1 => "x",: arg2 => "y"}
Conforme demonstrado no segundo exemplo, se você deseja usar espaços, as aspas ao redor do nome do destino são necessárias para impedir que o shell divida os argumentos no espaço.
Observando o código em rake.rb , parece que o rake não analisa seqüências de tarefas para extrair argumentos de pré-requisitos, portanto você não pode fazer isso task :t1 => "dep[1,2]"
. A única maneira de especificar argumentos diferentes para um pré-requisito seria invocá-lo explicitamente na ação da tarefa dependente, como em :invoke_my_task
e :invoke_my_task_2
.
Observe que algumas conchas (como zsh) exigem que você escape dos colchetes: rake my_task\['arg1'\]
WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
zsh: no matches found: ...
), então você precisa para escapar dos colchetes: rake my_task\['arg1'\]
. De robots.thoughtbot.com/post/18129303042/…
Além de responder por kch (não achei como deixar um comentário, desculpe):
Você não precisa especificar variáveis como ENV
variáveis antes do rake
comando. Você pode apenas defini-los como parâmetros de linha de comando usuais assim:
rake mytask var=foo
e acesse aqueles do seu arquivo rake como variáveis ENV como estas:
p ENV['var'] # => "foo"
p
significa?
Se você deseja passar argumentos nomeados (por exemplo, com padrão OptionParser
), pode usar algo como isto:
$ rake user:create -- --user test@example.com --pass 123
observe o --
que é necessário para ignorar os argumentos padrão do Rake. Deve trabalhar com Rake 0.9.x , <= 10.3.x .
O Rake mais recente mudou sua análise --
e agora você precisa garantir que não seja passado para o OptionParser#parse
método, por exemplo, comparser.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
no final, garantirá que os argumentos extras não serão interpretados como tarefa Rake.
Também o atalho para argumentos deve funcionar:
rake user:create -- -u test@example.com -p 123
Quando os scripts rake se parecem com isso, talvez seja hora de procurar outra ferramenta que permita isso imediatamente.
--option-names
. A minha única sugestão seria a utilização exit
, em vez de abort
como abort
vai deixar você com um código de retorno de 1 para o shell. Se a tarefa rake fizer parte de um script de nível superior, é mais comum assumir que uma saída diferente de zero é algum tipo de erro.
--
? Como passar rake
argumentos para a tarefa real ou algo assim? Gosta task :my_task, :*args do |t, args|
ou algo assim?
{username}
serve aqui. Onde é usado? Por que não está lá -u {username}
? Cheers
10.4.1
e revertida 10.4.2
. github.com/ruby/rake/commit/…
Encontrei a resposta desses dois sites: Net Maniac e Aimred .
Você precisa ter a versão> 0.8 do rake para usar esta técnica
A descrição normal da tarefa de rake é esta:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Para passar argumentos, faça três coisas:
Para acessar os argumentos no 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 chamar essa tarefa na linha de comando, passe os argumentos em [] s
rake task_name['Hello',4]
irá produzir
Hello
Hello
Hello
Hello
e se você quiser chamar essa tarefa de outra tarefa e passar argumentos, use invoke
task :caller do
puts 'In Caller'
Rake::Task[:task_name].invoke('hi',2)
end
então o comando
rake caller
irá produzir
In Caller
hi
hi
Não encontrei uma maneira de passar argumentos como parte de uma dependência, pois o código a seguir é quebrado:
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.
Outra opção comumente usada é passar variáveis de ambiente. No seu código, você os lê via ENV['VAR']
e pode transmiti-los antes do rake
comando, como
$ VAR=foo rake mytask
rake blah -- --these --go --to --a-program
(observe o aviso --
ao rake que seus switches terminaram), consulte stackoverflow.com/questions/5086224/…
Eu não conseguia descobrir como passar argumentos e também o ambiente: até resolver isso:
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 então eu chamo assim:
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]
Eu só queria poder executar:
$ rake some:task arg1 arg2
Simples, certo? (Não!)
O Rake interpreta arg1
e arg2
como tarefas, e tenta executá-las. Então, simplesmente abortamos antes que isso aconteça.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Tome isso, suportes!
Disclaimer : Eu queria ser capaz de fazer isso em um projeto bem pequeno para animais de estimação. Não se destina ao uso no "mundo real", pois você perde a capacidade de encadear tarefas de varredura (ou seja rake task1 task2 task3
). OMI não vale a pena. Basta usar o feio rake task[arg1,arg2]
.
_, arg1, arg2 = ARGV
pois o primeiro argumento foi visto como o nome da tarefa rake. Mas esse exit
é um truque legal.
rake task[arg1,arg2] && rake task2 && rake task3
Não tenho certeza se isso é menos feio do que rake task[arg1,arg2] task2 task3
. Provavelmente menos eficiente.
_, *args = ARGV
é perfeito para capturar todos os argumentos subseqüentes! Muito obrigado!
Eu uso um argumento ruby regular no arquivo rake:
DB = ARGV[1]
em seguida, elaborei as tarefas de rake na parte inferior do arquivo (pois o rake procurará uma tarefa com base no nome do argumento)
task :database_name1
task :database_name2
linha de comando:
rake mytask db_name
isso me parece mais limpo do que as soluções var = foo ENV var e a tarefa args [blah, blah2].
o esboço é um pouco instável, mas não muito ruim se você tiver apenas alguns ambientes que são uma configuração única
dup
no final: db = ARGV [1] .dup
db = ARGV[1].dup unless ARGV[1].nil?
para evitar a exceção de enganar um zero.
As maneiras de passar argumentos estão corretas na resposta acima. Entretanto, para executar tarefas de rake com argumentos, há um pequeno detalhe técnico envolvido na versão mais recente do rails
Ele funcionará com o rake "namespace: taskname ['argument1']"
Observe as aspas invertidas ao executar a tarefa na linha de comando.
Para passar argumentos para a tarefa padrão, você pode fazer algo assim. Por exemplo, diga "versão" é seu argumento:
task :default, [:version] => [:build]
task :build, :version do |t,args|
version = args[:version]
puts version ? "version is #{version}" : "no version passed"
end
Então você pode chamar assim:
$ 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
No entanto, não encontrei uma maneira de evitar a especificação do nome da tarefa (padrão ou compilação) durante a transmissão de argumentos. Gostaria de saber se alguém sabe de uma maneira.
Eu gosto da sintaxe "querystring" para a passagem de argumentos, especialmente quando há muitos argumentos a serem passados.
Exemplo:
rake "mytask[width=10&height=20]"
O "querystring" sendo:
width=10&height=20
Aviso: observe que a sintaxe é rake "mytask[foo=bar]"
e NÃO rake mytask["foo=bar"]
Quando analisado dentro da tarefa rake usando Rack::Utils.parse_nested_query
, obtemos um Hash
:
=> {"width"=>"10", "height"=>"20"}
(O legal é que você pode passar hashes e matrizes, mais abaixo)
Isto é como conseguir isso:
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
Aqui está um exemplo mais extenso que estou usando com o Rails na minha jóia 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]"
Analisado da mesma maneira que acima, com uma dependência de ambiente (para carregar o 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
Fornece o seguinte em options
=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}
Se você não se incomoda em lembrar qual é a posição do argumento e deseja fazer algo como um hash de argumento ruby. Você pode usar um argumento para passar uma sequência e depois regexá-la em um hash de opções.
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 na linha de comando você recebe.
$ 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
A maioria dos métodos descritos acima não funcionou para mim, talvez eles estejam obsoletos nas versões mais recentes. O guia atualizado pode ser encontrado aqui: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks
uma cópia e colar do manual está aqui:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
Invoque assim
bin/rake "task_name[value 1]" # entire argument string should be quoted
Para executar tarefas de rake com o estilo de argumentos tradicionais:
rake task arg1 arg2
E então use:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Adicione o seguinte patch da 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
Ao passar parâmetros, a melhor opção é um arquivo de entrada, pode ser um excel a json ou o que for necessário e, a partir daí, leia a estrutura de dados e as variáveis necessárias, incluindo o nome da variável conforme a necessidade. Ler um arquivo pode ter a seguinte estrutura.
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