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ć?
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
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'\]
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"
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.
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:
- Dodaj nazwy argumentów po nazwie zadania, oddzielone przecinkami.
- umieść zależności na końcu używając :needs = > [...]
- 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
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
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
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/']
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
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ą
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]
.
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ń.
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"}}
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.
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
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
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
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