Domanda

Ho un'attività rake che deve inserire un valore in più database.

Mi piacerebbe passare questo valore all'attività rake dalla riga di comando o da un altro compito di rastrello.

Come posso fare questo?

È stato utile?

Soluzione

opzioni e dipendenze devono essere 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: la variabile task è l'oggetto dell'attività, non molto utile a meno che tu non sappia / ti interessi degli interni di Rake.

NOTA BINARIO:

  

Se si esegue l'attività dai binari, è meglio precaricare l'ambiente aggiungendo => [:environment] che è un modo per impostare le attività dipendenti .

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

Altri suggerimenti

È possibile specificare argomenti formali nel rake aggiungendo argomenti simbolo alla chiamata attività. Ad esempio:

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

Quindi, dalla riga di 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"}

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 fare task :t1 => "dep[1,2]". L'unico modo per specificare argomenti diversi per un prerequisito sarebbe invocarlo esplicitamente nell'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'\]

Oltre a rispondere di kch (non ho trovato il modo di lasciare un commento, scusa):

Non è necessario specificare le variabili come ENV variabili prima del comando rake. 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"

Se vuoi passare argomenti con nome (ad es. con standard OptionParser) puoi usare qualcosa del genere:

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

osserva --, che è necessario per bypassare gli argomenti standard di Rake. Dovrebbe funzionare con Rake 0.9.x , & Lt; = 10.3.x .

Il rake più recente ha modificato l'analisi di OptionParser#parse e ora è necessario assicurarsi che non sia passato al metodo parser.parse!(ARGV[2..-1]), ad esempio con exit

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

<=> alla fine farà in modo 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 di rake sembrano così, forse è il momento di cercare un altro strumento che consenta questo appena pronto.

Ho trovato la risposta da questi due siti Web: Net Maniac e Aimred .

Devi avere la versione > 0,8 di rake per usare questa tecnica

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:

  1. Aggiungi i nomi degli argomenti dopo il nome dell'attività, separati da virgole.
  2. Metti le dipendenze alla fine usando: needs = > [...]
  3. Posiziona | t, args | dopo il do. (t è l'oggetto per questa attività)

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]

verrà emesso

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

verrà emesso

In Caller
hi
hi

Non ho trovato il modo di passare argomenti come parte di una dipendenza, poiché il seguente codice si rompe:

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

Un'altra opzione comunemente usata è passare variabili d'ambiente. Nel tuo codice li leggi tramite ENV['VAR'] e puoi passarli subito prima del comando rake, come

$ VAR=foo rake mytask

In realtà @Nick Desjardins ha risposto perfettamente. Ma solo per l'istruzione: puoi usare un approccio sporco: usando ENV argomento

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

rake my_task myvar=10
#=> myvar: 10

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

Volevo solo essere in grado di eseguire:

$ rake some:task arg1 arg2

Semplice, vero? (No!)

Rake interpreta arg1 e arg2 come attività e tenta 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 inteso per & Quot; mondo reale & Quot; utilizzo poiché perdi la possibilità di concatenare attività di rastrellamento (ad es. rake task1 task2 task3). IMO non ne vale la pena. Usa il brutto rake task[arg1,arg2].

Utilizzo un normale argomento ruby ​​nel file rake:

DB = ARGV[1]

quindi elimino le attività rake nella parte inferiore del file (poiché rake cercherà un'attività in base a quel nome di argomento).

task :database_name1
task :database_name2

riga di comando:

rake mytask db_name

questo mi sembra più pulito delle soluzioni var=foo ENV var e task args[blah, blah2].
lo stub è un po' traballante, ma non troppo male se hai solo alcuni ambienti che sono una configurazione una tantum

I modi per passare l'argomento sono corretti nella risposta sopra. Tuttavia, per eseguire attività rake con argomenti, c'è un piccolo tecnicismo coinvolto nella versione più recente delle rotaie

Funzionerà con rake " namespace: taskname ['argomento1'] "

Nota le virgolette invertite nell'esecuzione dell'attività dalla riga di comando.

Mi piace il " querystring " sintassi per il passaggio degli argomenti, soprattutto quando ci sono molti argomenti da passare.

Esempio:

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

Il " querystring " essere:

width=10&height=20

Avviso: nota che la sintassi è rake "mytask[foo=bar]" e NON rake mytask["foo=bar"]

Quando analizzato all'interno dell'attività di 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 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]"

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 in options

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

Per passare argomenti all'attività predefinita, puoi fare qualcosa del genere. Ad esempio, diciamo & Quot; & Versione quot; è 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.

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-task

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

Se non puoi essere disturbato a ricordare quale posizione dell'argomento è per cosa e vuoi fare qualcosa come un hash dell'argomento ruby. È possibile utilizzare un argomento per passare una stringa e quindi regexare quella stringa in un hash di 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

Per eseguire attività 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 si passano 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

Esempio json

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

Esecuzione

rake :name_task 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top