Pergunta

Eu tenho uma tarefa rake que precisa inserir um valor em vários bancos de dados.

Eu gostaria de passar esse valor na tarefa rake a partir da linha de comando, ou a partir de outro tarefa rake.

Como posso fazer isso?

Foi útil?

Solução

opções e dependências preciso 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

Em seguida

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: variable task é o objeto tarefa, não muito útil se você não sabe / cuidado sobre o funcionamento interno do ancinho.

TRILHOS NOTA:

Se você estiver executando a tarefa de trilhos, o seu melhor para pré-carregar o ambiente, adicionando => [:environment] que é uma maneira de configurar dependentes tarefas.

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

Outras dicas

Você pode especificar argumentos formais em rake, acrescentando argumentos símbolo para a chamada de tarefa. Por exemplo:

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

Em seguida, a partir da linha de comando:

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

Como demonstrado no segundo exemplo, se você quiser utilizar espaços, as aspas em torno do nome de destino são necessárias para manter a casca de dividir os argumentos no espaço.

Olhando para o código em rake.rb , parece que ancinho não analisa seqüências de tarefas para argumentos Extrato de pré-requisitos, então você não pode fazer task :t1 => "dep[1,2]". A única maneira de especificar diferentes argumentos para um pré-requisito seria para invocá-lo explicitamente no âmbito da acção tarefa dependente, como em :invoke_my_task e :invoke_my_task_2.

Note que algumas conchas (como zsh) exigem que você escapar do parêntesis: rake my_task\['arg1'\]

Além de resposta por kch (eu não veja como deixe um comentário para que, sorry):

Você não tem que especificar variáveis ??como variáveis ??ENV antes do comando rake. Você pode apenas configurá-los como parâmetros habituais de linha de comando como o seguinte:

rake mytask var=foo

e acesso aqueles de seu arquivo ancinho como variáveis ??ENV como tal:

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

Se você quer passar argumentos nomeados (por exemplo, com OptionParser padrão), você pode usar algo como isto:

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

observe o --, o que é necessário para contornar argumentos Rake padrão. Deve trabalhar com Rake 0.9.x , <= 10.3.x .

recente Rake mudou sua análise de --, e agora você tem que ter certeza que não é passado para o método OptionParser#parse, por exemplo, com 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 no final irá certificar-se que os argumentos extras não será interpretado como tarefa Rake.

Além disso, o atalho para argumentos deve funcionar:

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

Quando os scripts de rake parecido com este, talvez seja hora de olhar para outra ferramenta que permitiria que este apenas fora da caixa.

Eu encontrei a resposta destes dois sites: Maniac Net e Aimred .

Você precisa ter versão> 0.8 de rake para usar esta técnica

A descrição normal de tarefa rake é o seguinte:

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

Para passar argumentos, fazer três coisas:

  1. Adicione os nomes de argumentos depois do nome da tarefa, separados por vírgulas.
  2. Coloque as dependências no final usando: necessidades => [...]
  3. Coloque | t, args | após o tumulto. (T é o objeto para esta tarefa)

Para acessar os argumentos no script, o uso 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 esta tarefa a partir da linha de comando, passe-os argumentos em [] s

rake task_name['Hello',4]

saída vontade

Hello
Hello
Hello
Hello

e se você quiser chamar esta tarefa a partir de uma outra tarefa, e passá-lo argumentos, o uso de invocação

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

então o comando

rake caller

saída vontade

In Caller
hi
hi

Eu não encontrei uma maneira de passar argumentos como parte de uma dependência, como as quebras de código a seguir:

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

Outra opção é comumente usado para passar variáveis ??de ambiente. Em seu código você lê-los via ENV['VAR'], e pode passá-los para a direita antes do comando rake, como

$ VAR=foo rake mytask

Na verdade @ Nick Desjardins respondeu perfeito. Mas só para a educação: você pode usar abordagem suja: usando argumento ENV

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

rake my_task myvar=10
#=> myvar: 10

Eu não conseguia descobrir como passar args e também a: ambiente até que eu trabalhei 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

Eu só queria ser capaz de executar:

$ rake some:task arg1 arg2

Simples, certo? (Não!)

interpreta Rake arg1 e arg2 como tarefas, e tenta executá-los. Então, nós apenas abortar antes que ele faz.

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

    # your task...

    exit
  end
end

Tome isso, suportes!

Aviso : eu queria ser capaz de fazer isso em um muito pequeno projeto de estimação. Não se destina para uso "mundo real", uma vez que você perde a capacidade de tarefas rake cadeia (ou seja rake task1 task2 task3). IMO não vale a pena. Basta usar o rake task[arg1,arg2] feio.

Eu uso um argumento regulares ruby ??no arquivo ancinho:

DB = ARGV[1]

então eu stub as tarefas rake na parte inferior do arquivo (desde ancinho vai olhar para uma tarefa com base nesse nome do argumento).

task :database_name1
task :database_name2

linha de comando:

rake mytask db_name

este se sente mais limpo para mim do que a var = var foo ENV e os argumentos de tarefas [blah, blah2] soluções.
o stub é um pouco Jenky, mas não muito ruim se você só tem alguns ambientes que são uma configuração única

As formas de passar argumento está correto em resposta acima. No entanto, para executar tarefa rake com argumentos, há um pequeno detalhe técnico envolvido na versão mais recente do rails

Ele vai trabalhar com o ancinho "namespace: taskname [ 'argument1']"

Observe as aspas invertidas em executar a tarefa a partir da linha de comando.

Eu gosto da sintaxe "querystring" para a passagem argumento, especialmente quando há um monte de argumentos a serem passados.

Exemplo:

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

O "querystring" ser:

width=10&height=20

Aviso: Note 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, temos um Hash:

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

(O legal é que você pode passar hashes e arrays, mais abaixo)

Este é 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 prolongado que eu estou usando com Rails na minha delayed_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]"

Parsed da mesma maneira como acima, com uma dependência ambiente (na ordem de carga do ambiente trilhos)

namespace :dj do
  task :start, [ :args_expr ] => :environment do |t, args|
    # defaults here...
    options = Rack::Utils.parse_nested_query(args[:args_expr])  
  end
end

profere o presente em options

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

Para passar argumentos para a tarefa padrão, você pode fazer algo como isto. Por exemplo, digamos "Versão" é 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

Em seguida, você pode chamá-lo 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, eu não encontrei uma maneira de evitar especificando o nome da tarefa (padrão ou de construção), enquanto passando em argumentos. Gostaria de saber se alguém sabe de uma maneira.

A maioria dos métodos descritos acima não funcionou para mim, talvez eles são preteridos nas versões mais recentes. O guia de up-to-date pode ser encontrada aqui: http: //guides.rubyonrails .org / command_line.html # costume-ancinho-tarefas

a copiar-e-colar ans do guia está aqui:

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

invocá-lo como este

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

Se você não pode ser incomodado para lembrar que posição argumento é para o que e você quer fazer algo como um hash argumento rubi. Você pode usar um argumento para passar uma cadeia e, em seguida, regex que string 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 que você começa.

$ 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

Para executar tarefas rake com estilo argumentos tradicionais:

rake task arg1 arg2

E, em seguida, use:

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

Adicionar seguinte patch de gem ancinho:

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, é melhor opção é um arquivo de entrada, isso pode ser um excel um JSON ou o que você precisa e de lá ler a estrutura de dados e variáveis ??que você precisa de que a inclusão do nome da variável como é a necessidade. Para 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

Exemplo json

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

Execução

rake :name_task 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top