Mam zadanie prowizji, które musi wstawić wartość do wielu baz danych.
Chciałbym przekazać tę wartość do zadania prowizji z wiersza poleceń lub innego zadania prowizji.
W jaki sposób mogę to zrobić?
Mam zadanie prowizji, które musi wstawić wartość do wielu baz danych.
Chciałbym przekazać tę wartość do zadania prowizji z wiersza poleceń lub innego zadania prowizji.
W jaki sposób mogę to zrobić?
Odpowiedzi:
opcje i zależności muszą znajdować się 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
Następnie
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 wiesz / dbasz o elementy wewnętrzne Rake.
UWAGA SZYNY:
W przypadku uruchamiania zadania z szyn najlepiej jest wstępnie załadować środowisko, dodając
=> [:environment]
sposób konfigurowania zadań zależnych .
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
rake thing:work[1, 2, 3]
ponieważ to nie zadziała, a otrzymasz błądDon't know how to build task
rake thing:work'[1,2,3]'
rake thing:work\[1,2,3\]
lub tenrake 'thing:work[1,2,3]'
:environment
symbol ze swojego zadania. aplikacje szynowe mają: zadanie środowiskowe ...
t
oznacza task
, dlaczego nie użyć po prostu task
nazwy param?
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} 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
Następnie z wiersza poleceń:
> rake my_task [1, false] Argumentami były: {: arg1 => „1”,: arg2 => „false”} klasy Rake :: TaskArguments arg1 było: „1” klasy String arg2 to: „false” klasy String > rake „my_task [1, 2]” Argumentami były: {: arg1 => „1”,: arg2 => „2”} > rake invoke_my_task Argumentami były: {: arg1 => „1”,: arg2 => „2”} > rake invoke_my_task_2 Argumentami były: {: arg1 => 3,: arg2 => 4} > rake with_prerequisite [5,6] Argumentami były: {: arg1 => „5”,: arg2 => „6”} > rake with_defaults Argumenty z wartościami domyślnymi to: {: arg1 =>: default_1,: arg2 =>: default_2} > rake with_defaults ['x', 'y'] Argumenty z wartościami domyślnymi to: {: arg1 => "x",: arg2 => "y"}
Jak pokazano w drugim przykładzie, jeśli chcesz używać spacji, cudzysłowy wokół nazwy celu są niezbędne, aby powłoka nie dzieliła argumentów w przestrzeni.
Patrząc na kod w rake.rb , okazuje się, że rake nie analizuje ciągów zadań w celu wyodrębnienia argumentów dotyczących wymagań 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 wstępnego byłoby jawne wywołanie go w ramach 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: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
zsh: no matches found: ...
), więc trzeba się uciec wsporniki: rake my_task\['arg1'\]
. Z robots.thoughtbot.com/post/18129303042/…
Oprócz odpowiedzi autorstwa kcha (przepraszam, nie znalazłem sposobu na pozostawienie komentarza):
Nie musisz określać zmiennych jako ENV
zmiennych przed rake
poleceniem. Możesz po prostu ustawić je jako zwykłe parametry wiersza poleceń:
rake mytask var=foo
i uzyskaj dostęp do tych z pliku rake jako zmienne ENV takie jak:
p ENV['var'] # => "foo"
p
oznacza?
Jeśli chcesz przekazać nazwane argumenty (np. Ze standardem OptionParser
), możesz użyć czegoś takiego:
$ rake user:create -- --user test@example.com --pass 123
zwróć uwagę --
, że jest to konieczne do ominięcia standardowych argumentów Rake. Powinien pracować z prowizji 0.9.x , <= 10.3.x .
Nowszy Rake zmienił swoje parsowanie --
, a teraz musisz się upewnić, że nie został przekazany do OptionParser#parse
metody, na przykład zparser.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 Rake.
Skrót do argumentów powinien również działać:
rake user:create -- -u test@example.com -p 123
Kiedy skrypty rake wyglądają tak, być może nadszedł czas, aby poszukać innego narzędzia, które pozwoliłoby na to po wyjęciu z pudełka.
--option-names
. Moją jedyną propozycją byłoby użycie exit
zamiast, abort
ponieważ abort
pozostawi ci kod powrotu 1 do powłoki. Jeśli zadanie prowizji jest częścią skryptu wyższego poziomu, częściej przyjmuje się, że niezerowe wyjście jest rodzajem błędu.
--
? Jak przekazywanie rake
argumentów do faktycznego zadania czy coś? Lubisz task :my_task, :*args do |t, args|
czy coś?
{username}
tu jest. Gdzie jest używany? Dlaczego tego nie ma -u {username}
? Na zdrowie
10.4.1
i przywrócony 10.4.2
. github.com/ruby/rake/commit/…
Znalazłem odpowiedź z tych dwóch stron internetowych: Net Maniac i Aimred .
Aby skorzystać z tej techniki, musisz mieć wersję> 0,8 rake'u
Normalny opis zadania rake jest następujący:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Aby przekazać argumenty, wykonaj trzy czynności:
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 wiersza poleceń, przekaż mu argumenty w [] s
rake task_name['Hello',4]
wyjdzie
Hello
Hello
Hello
Hello
a 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
wyjdzie
In Caller
hi
hi
Nie znalazłem sposobu na przekazywanie argumentów jako części zależności, ponieważ następujący kod się psuje:
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.
Inną często stosowaną opcją jest przekazywanie zmiennych środowiskowych. W swoim kodzie czytasz je przez ENV['VAR']
i możesz przekazać je tuż przed rake
poleceniem, na przykład
$ VAR=foo rake mytask
rake blah -- --these --go --to --a-program
(zwróć uwagę na --
prowizję, że jej przełączniki się zakończyły), patrz stackoverflow.com/questions/5086224/…
Nie mogłem wymyślić, jak przekazywać argumenty, a także: środowisko, dopóki nie opracowałem tego:
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 dzwonię w ten sposób:
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]
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 nastąpi.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Weź to, nawiasy!
Oświadczenie : Chciałem móc to zrobić w dość małym projekcie dla zwierząt. Nie jest przeznaczony do użycia w „świecie rzeczywistym”, ponieważ tracisz możliwość łączenia zadań rake (tj rake task1 task2 task3
.). IMO nie jest tego warte. Po prostu użyj brzydkiego rake task[arg1,arg2]
.
_, arg1, arg2 = ARGV
ponieważ pierwszy argument był nazwą zadania rake. Ale exit
to fajna sztuczka.
rake task[arg1,arg2] && rake task2 && rake task3
Nie jestem pewien, czy to mniej brzydkie niż rake task[arg1,arg2] task2 task3
. Prawdopodobnie mniej wydajny.
_, *args = ARGV
jest idealny do przechwytywania wszystkich kolejnych argumentów! Dzięki stosy!
Używam zwykłego argumentu ruby w pliku rake:
DB = ARGV[1]
następnie usuwam zadania rake na dole pliku (ponieważ rake wyszuka zadanie na podstawie nazwy tego argumentu).
task :database_name1
task :database_name2
wiersz poleceń:
rake mytask db_name
wydaje mi się to czystsze niż var = foo ENV var i zadanie argumentuje [bla, bla2] rozwiązania.
odgałęzienie jest trochę szarpane, ale nie jest takie złe, jeśli masz tylko kilka środowisk, które są jednorazową konfiguracją
dup
na końcu: db = ARGV [1] .dup
db = ARGV[1].dup unless ARGV[1].nil?
aby uniknąć wyjątku kopiowania zera.
Sposoby przekazywania argumentu są poprawne w powyższej odpowiedzi. Jednak aby uruchomić zadanie rake z argumentami, w nowszej wersji szyn występuje niewielka technika
Będzie działał z prowizją „namespace: taskname ['argument1']"
Zwróć uwagę na odwrócone cudzysłowy podczas uruchamiania zadania z wiersza poleceń.
Aby przekazać argumenty do domyślnego zadania, możesz zrobić coś takiego. Na przykład powiedz „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
Możesz 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
Jednak nie znalazłem sposobu, aby uniknąć podania nazwy zadania (domyślnej lub kompilacji) podczas przekazywania argumentów. Chciałbym usłyszeć, jeśli ktoś zna sposób.
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” to:
width=10&height=20
Ostrzeżenie: zauważ, że składnia jest rake "mytask[foo=bar]"
i NIE rake mytask["foo=bar"]
Po przeanalizowaniu za pomocą zadania prowizji Rack::Utils.parse_nested_query
otrzymujemy Hash
:
=> {"width"=>"10", "height"=>"20"}
(Fajne jest to, że możesz przekazywać skróty i tablice, więcej poniżej)
Oto jak to osiągnąć:
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 Railsami w moim klejnocie z opóźnieniem_obrotu_aktywnego_rejestrowania_recordu :
bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"
Przetwarzane w taki sam sposób jak powyżej, z zależnością ś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"}}
Jeśli nie możesz zaprzątać sobie głowy zapamiętywaniem, która pozycja argumentu jest dla czego, i chcesz zrobić coś w rodzaju skrótu argumentu ruby. Możesz użyć jednego argumentu, aby przekazać ciąg, a następnie ponownie wyrejestruj ten ciąg do skrótu 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ń pojawi się.
$ 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
Większość opisanych powyżej metod nie działała dla mnie, być może są one przestarzałe w nowszych wersjach. Aktualny przewodnik można znaleźć tutaj: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks
Skopiuj 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 w ten sposób
bin/rake "task_name[value 1]" # entire argument string should be quoted
Aby uruchomić zadania prowizji z tradycyjnym stylem argumentów:
rake task arg1 arg2
A następnie użyj:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Dodaj następującą łatkę klejnotu prowizji:
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
Podczas przekazywania parametrów lepszym rozwiązaniem jest plik wejściowy, czy może to być excel json lub cokolwiek potrzebujesz, a stamtąd odczytaj potrzebną strukturę danych i zmienne, w tym nazwę zmiennej. Aby odczytać plik, 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
{
"name_task": "I'm a task",
"user_id": 389,
"users_assigned": [389,672,524],
"task_id": 3
}
rake :name_task