Jak przekazać argumenty wiersza poleceń do zadania rake

Mam zadanie rake, które wymaga Wstawienia wartości do wielu baz danych.

Chciałbym przekazać tę wartość do zadania rake z linii poleceń, lub z innego zadania rake.

Jak mogę to zrobić?

Author: the Tin Man, 2009-05-05

17 answers

Opcje i zależności muszą być wewnątrz tablic:

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

Then

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

Uwaga: zmienna task jest obiektem zadania, niezbyt pomocnym, chyba że znasz / dbasz o wewnętrzne funkcje Rake ' a.

RAILS NOTE:

Jeśli uruchamiamy zadanie z rails, najlepiej jest wstępnie załadować środowisko przez dodanie => [:environment], co jest sposobem na ustawienie zależnych zadań.

  task :work, [:option, :foo, :bar] => [:environment] do |task, args|
    puts "work", args
  end
 240
Author: Blair Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-11 19:22:00

Możesz określić formalne argumenty w rake, dodając argumenty symboli do wywołania zadania. Na przykład:

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

Następnie z linii poleceń:

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

Jak pokazano w drugim przykładzie, jeśli chcesz używać spacji, cudzysłowy wokół nazwy docelowej są konieczne, aby powłoka nie dzieliła argumentów w spacji.

Patrząc na kod w grabie.rb, wygląda na to, że rake nie parsuje łańcuchów zadań, aby wyodrębnić argumenty dla warunków wstępnych, więc nie możesz tego zrobić task :t1 => "dep[1,2]". Jedynym sposobem na określenie różnych argumentów dla warunku jest jawne wywołanie go w zależnej akcji zadania, jak w :invoke_my_task i :invoke_my_task_2.

Zauważ, że niektóre powłoki (jak zsh) wymagają ucieczki od nawiasów: rake my_task\['arg1'\]

 1084
Author: Nick Desjardins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-08 15:32:57

Oprócz odpowiedzi kch (nie znalazłem jak zostawić komentarz do tego, przepraszam):

Nie musisz określać zmiennych jako zmienne ENV przed poleceniem rake. Możesz po prostu ustawić je jako zwykłe parametry wiersza poleceń w ten sposób:

rake mytask var=foo

I uzyskaj dostęp do tych z pliku rake jako zmienne ENV, takie jak:

p ENV['var'] # => "foo"
 292
Author: timurb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-16 19:35:18

Jeśli chcesz przekazać argumenty nazwane (np. ze standardowym OptionParser), możesz użyć czegoś takiego:

$ rake user:create -- --user [email protected] --pass 123

Zwróć uwagę na --, która jest niezbędna do pominięcia standardowych argumentów Rake. Powinno działać z Rake 0.9.x, .

Nowszy Rake zmienił swoje parsowanie --, a teraz musisz się upewnić, że nie został przekazany do metody OptionParser#parse, na przykład z 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 na końcu upewni się, że dodatkowe argumenty nie będą interpretowane jako zadanie prowizji.

Również skrót argumentów powinien działać:

 rake user:create -- -u [email protected] -p 123

Kiedy Skrypty rake wyglądają tak, może nadszedł czas, aby poszukać innego narzędzia, które pozwoliłoby na to po prostu out of box.

 97
Author: Tombart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-11 10:49:28

Znalazłem odpowiedź z tych dwóch stron: Net Maniac i Aimred .

Aby użyć tej techniki, musisz mieć wersję > 0.8 rake ' a

Normalny opis zadania grabie jest następujący:

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

Aby przekazać argumenty, zrób trzy rzeczy:

  1. Dodaj nazwy argumentów po nazwie zadania, oddzielone przecinkami.
  2. umieść zależności na końcu używając :needs = > [...]
  3. Place / t, args / after the do. (t jest obiektem dla to zadanie)

Aby uzyskać dostęp do argumentów w skrypcie, użyj 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

Aby wywołać to zadanie z linii poleceń, podaj mu argumenty w [] s

rake task_name['Hello',4]

Wyświetli

Hello
Hello
Hello
Hello

I jeśli chcesz wywołać to zadanie z innego zadania i przekazać mu argumenty, użyj invoke

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

Następnie polecenie

rake caller

Wyświetli

In Caller
hi
hi

Nie znalazłem sposobu, aby przekazać argumenty jako część zależności, ponieważ poniższy kod przerwy:

task :caller => :task_name['hi',2]' do
   puts 'In Caller'
end
 56
Author: Tilendor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-05 16:51:45

Inną powszechnie używaną opcją jest przekazanie zmiennych środowiskowych. W swoim kodzie odczytujesz je za pomocą ENV['VAR'] i możesz przekazać je tuż przed rake poleceniem, jak

$ VAR=foo rake mytask
 30
Author: kch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-05 16:53:13

@ Nick Desjardins odpowiedział idealnie. Ale tylko dla edukacji: możesz użyć dirty approach: using ENV argument

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

rake my_task myvar=10
#=> myvar: 10
 30
Author: fl00r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-28 20:06:33

Nie mogłem wymyślić, jak przekazać args, a także :environment, dopóki tego nie rozgryzłem:

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

A potem wołam TAK:

rake db:export['foo, /tmp/']
 24
Author: Nate Flink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-29 19:38:18
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end
 23
Author: Feng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-16 07:36:27

Używam zwykłego argumentu ruby w pliku rake:

DB = ARGV[1]

Następnie sprawdzam zadania rake na dole pliku (ponieważ rake będzie szukał zadania na podstawie nazwy argumentu).

task :database_name1
task :database_name2

Wiersz poleceń:

rake mytask db_name

Wydaje mi się to czystsze niż var=foo ENV var i rozwiązania task args[blah, blah2].
stub jest trochę jenky, ale nie jest tak źle, jeśli masz tylko kilka środowisk, które są konfiguracją jednorazową

 13
Author: djburdick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-29 02:48:52

Chciałem tylko móc biegać:

$ rake some:task arg1 arg2
Proste, prawda? (Nie!) Rake interpretuje arg1 i arg2 jako zadania i próbuje je uruchomić. Więc po prostu przerywamy zanim to się stanie.
namespace :some do
  task task: :environment do
    arg1, arg2 = ARGV

    # your task...

    exit
  end
end

Weź to, nawiasy!

Disclaimer: chciałem być w stanie to zrobić w dość małym projekcie dla zwierząt. Nie jest przeznaczony do użytku w "realnym świecie", ponieważ tracisz możliwość łączenia zadań prowizji (np. rake task1 task2 task3). IMO nie warto. Wystarczy użyć brzydkiego rake task[arg1,arg2].

 13
Author: jassa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-17 22:20:57

Sposoby przekazywania argumentów są poprawne w powyższej odpowiedzi. Jednak, aby uruchomić zadanie rake z argumentami, w nowszej wersji rails występuje mała techniczna potrzeba

Będzie działać z rake " namespace: taskname['argument1'] "

Zwróć uwagę na odwrócone cudzysłowy podczas uruchamiania zadania z linii poleceń.

 5
Author: Asim Mushtaq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-05 07:21:16

Podoba mi się składnia" querystring " do przekazywania argumentów, szczególnie gdy jest wiele argumentów do przekazania.

Przykład:

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

"querystring" byt:

width=10&height=20

Warning: zauważ, że składnia to rake "mytask[foo=bar]" i Nie rake mytask["foo=bar"]

Po przetworzeniu wewnątrz zadania rake za pomocą Rack::Utils.parse_nested_query, otrzymujemy Hash:

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

(najfajniejsze jest to, że możesz przekazywać hasze i tablice, więcej poniżej)

Oto jak osiągnąć to:

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

Oto bardziej rozbudowany przykład, którego używam z Rails w moim 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]"

Parsowane tak samo jak wyżej, z zależnością od środowiska (w celu załadowania środowiska 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

Daje następujące w options

=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}
 4
Author: Abdo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-16 22:05:07

Aby przekazać argumenty do domyślnego zadania, możesz zrobić coś takiego. Na przykład, powiedzmy "wersja" to twój argument:

task :default, [:version] => [:build]

task :build, :version do |t,args|
  version = args[:version]
  puts version ? "version is #{version}" : "no version passed"
end

Wtedy można to tak nazwać:

$ rake
no version passed

Lub

$ rake default[3.2.1]
version is 3.2.1

Lub

$ rake build[3.2.1]
version is 3.2.1

Nie znalazłem jednak sposobu, aby uniknąć podania nazwy zadania (domyślnie lub build) podczas przekazywania argumentów. Chciałbym usłyszeć, czy ktoś zna sposób.

 3
Author: Gal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-20 19:03:37

Większość opisanych powyżej metod nie działa dla mnie, może są przestarzałe w nowszych wersjach. Aktualny przewodnik można znaleźć tutaj: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks

Kopiuj i wklej ans z przewodnika jest tutaj:

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

Wywołaj to tak

bin/rake "task_name[value 1]" # entire argument string should be quoted
 2
Author: hexinpeter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-03 01:15:17

Jeśli nie możesz sobie przypomnieć, jaka pozycja argumentu jest dla czego i chcesz zrobić coś takiego jak hash argumentu ruby. Możesz użyć jednego argumentu, aby przekazać ciąg znaków, a następnie ponownie dodać go do hasha opcji.

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

I w wierszu poleceń dostajesz.

$ 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
 1
Author: xander-miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-12 01:44:06

Podczas przekazywania parametrów, lepszym rozwiązaniem jest plik wejściowy, może to być excel, json lub cokolwiek, czego potrzebujesz, a stamtąd odczytaj strukturę danych i zmienne, których potrzebujesz z tego, w tym nazwę zmiennej, jak jest potrzeba. Odczyt pliku może mieć następującą strukturę.

  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

Przykład json

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

Egzekucja

rake :name_task 
 -4
Author: tundervirld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-11 23:43:07