Ich habe eine Rechenaufgabe, die einen Wert in mehrere Datenbanken einfügen muss.
Ich möchte diesen Wert über die Befehlszeile oder über eine andere Rechenaufgabe an die Rechenaufgabe übergeben.
Wie kann ich das machen?
Ich habe eine Rechenaufgabe, die einen Wert in mehrere Datenbanken einfügen muss.
Ich möchte diesen Wert über die Befehlszeile oder über eine andere Rechenaufgabe an die Rechenaufgabe übergeben.
Wie kann ich das machen?
Antworten:
Optionen und Abhängigkeiten müssen sich in Arrays befinden:
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
Dann
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"}
HINWEIS: Variable
task
ist das Aufgabenobjekt, das nur dann sehr hilfreich ist, wenn Sie sich mit Rake-Interna auskennen.
SCHIENEN HINWEIS:
Wenn Sie die Aufgabe von Rails aus ausführen, laden Sie die Umgebung am besten vor, indem Sie sie hinzufügen
=> [:environment]
, um abhängige Aufgaben einzurichten .
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
rake thing:work[1, 2, 3]
da es nicht funktioniert und du einen Fehler Don't know how to build task
rake thing:work'[1,2,3]'
rake thing:work\[1,2,3\]
rake 'thing:work[1,2,3]'
:environment
Symbol aus Ihrer Aufgabe entfernen . Schienenanwendungen haben eine: Umweltaufgabe ...
t
Mittel task
, warum nicht nur verwenden , task
als param name?
Sie können formale Argumente in Rake angeben, indem Sie dem Taskaufruf Symbolargumente hinzufügen. Zum Beispiel:
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
Dann von der Kommandozeile:
> harke my_task [1, false] Argumente waren: {: arg1 => "1" ,: arg2 => "false"} der Klasse Rake :: TaskArguments arg1 war: '1' der Klasse String arg2 war: 'false' der Klasse String > Rechen "my_task [1, 2]" Argumente waren: {: arg1 => "1" ,: arg2 => "2"} > Rechen invoke_my_task Argumente waren: {: arg1 => "1" ,: arg2 => "2"} > Rechen invoke_my_task_2 Argumente waren: {: arg1 => 3 ,: arg2 => 4} > Rechen mit Voraussetzung [5,6] Argumente waren: {: arg1 => "5" ,: arg2 => "6"} > Rechen mit_defaults Argumente mit Standardwerten waren: {: arg1 =>: default_1 ,: arg2 =>: default_2} > Rechen mit_defaults ['x', 'y'] Argumente mit Standardwerten waren: {: arg1 => "x" ,: arg2 => "y"}
Wie im zweiten Beispiel gezeigt, sind die Anführungszeichen um den Zielnamen erforderlich, wenn Sie Leerzeichen verwenden möchten, damit die Shell die Argumente im Leerzeichen nicht aufteilt.
Wenn Sie sich den Code in rake.rb ansehen , scheint es, dass Rake keine Task-Strings analysiert, um Argumente für die Voraussetzungen zu extrahieren. Dies ist also nicht möglich task :t1 => "dep[1,2]"
. Die einzige Möglichkeit, unterschiedliche Argumente für eine Voraussetzung anzugeben, besteht darin, sie explizit innerhalb der abhängigen Taskaktion wie in :invoke_my_task
und aufzurufen :invoke_my_task_2
.
Beachten Sie, dass Sie bei einigen Shells (wie zsh) die Klammern verlassen müssen: rake my_task\['arg1'\]
WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
zsh: no matches found: ...
), sodass Sie die Klammern umgehen müssen : rake my_task\['arg1'\]
. Von robots.thoughtbot.com/post/18129303042/…
Zusätzlich zur Antwort von kch (ich habe nicht gefunden, wie ich einen Kommentar dazu hinterlassen kann, sorry):
Sie müssen ENV
vor dem rake
Befehl keine Variablen als Variablen angeben . Sie können sie einfach wie gewohnt wie folgt festlegen:
rake mytask var=foo
und greifen Sie auf diese aus Ihrer Rake-Datei als ENV-Variablen wie diese zu:
p ENV['var'] # => "foo"
p
?
Wenn Sie benannte Argumente übergeben möchten (z. B. mit Standard OptionParser
), können Sie Folgendes verwenden:
$ rake user:create -- --user test@example.com --pass 123
Beachten Sie --
, dass dies erforderlich ist, um Standard-Rake-Argumente zu umgehen. Sollte die Arbeit mit Rechen 0.9.x , <= 10.3.x .
Newer Rake hat das Parsen von geändert --
, und jetzt müssen Sie sicherstellen, dass es nicht an die OptionParser#parse
Methode übergeben wird, z. B. mitparser.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
Am Ende wird sichergestellt, dass die zusätzlichen Argumente nicht als Rechenaufgabe interpretiert werden.
Auch die Verknüpfung für Argumente sollte funktionieren:
rake user:create -- -u test@example.com -p 123
Wenn Rake-Skripte so aussehen, ist es vielleicht an der Zeit, nach einem anderen Tool zu suchen, mit dem dies sofort möglich ist.
--option-names
. Mein einziger Vorschlag wäre, zu verwenden , exit
anstatt abort
wie abort
werden Sie mit einem Return - Code von 1 an dem Shell verlassen. Wenn die Rake-Task Teil eines übergeordneten Skripts ist, wird häufiger angenommen, dass ein Exit ungleich Null eine Art Fehler ist.
--
? Wie rake
Argumente an die eigentliche Aufgabe weitergeben oder so? Wie task :my_task, :*args do |t, args|
oder so?
{username}
hier ist. Wo wird es verwendet? Warum ist es nicht da drin -u {username}
? Prost
10.4.1
und Weise, wie Rake ARGV analysiert, wurde geändert und zurückgesetzt 10.4.2
. github.com/ruby/rake/commit/…
Ich habe die Antwort von diesen beiden Websites gefunden: Net Maniac und Aimred .
Sie benötigen eine Version> 0,8 von Rake, um diese Technik verwenden zu können
Die normale Beschreibung der Rechenaufgabe lautet wie folgt:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Führen Sie drei Schritte aus, um Argumente zu übergeben:
Verwenden Sie args.arg_name, um auf die Argumente im Skript zuzugreifen
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
Um diese Aufgabe über die Befehlszeile aufzurufen, übergeben Sie ihr die Argumente in [] s
rake task_name['Hello',4]
wird ausgegeben
Hello
Hello
Hello
Hello
Wenn Sie diese Aufgabe von einer anderen Aufgabe aus aufrufen und ihr Argumente übergeben möchten, verwenden Sie invoke
task :caller do
puts 'In Caller'
Rake::Task[:task_name].invoke('hi',2)
end
dann der Befehl
rake caller
wird ausgegeben
In Caller
hi
hi
Ich habe keine Möglichkeit gefunden, Argumente als Teil einer Abhängigkeit zu übergeben, da der folgende Code unterbrochen wird:
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.
Eine weitere häufig verwendete Option ist die Übergabe von Umgebungsvariablen. In Ihrem Code lesen Sie sie über ENV['VAR']
und können sie direkt vor dem rake
Befehl übergeben, wie
$ VAR=foo rake mytask
rake blah -- --these --go --to --a-program
(Beachten Sie die --
, um Rake mitzuteilen, dass seine Schalter beendet sind), siehe stackoverflow.com/questions/5086224/…
Ich konnte nicht herausfinden, wie man Argumente und auch die: Umgebung weitergibt, bis ich das herausgefunden habe:
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
Und dann rufe ich so an:
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]
Ich wollte nur laufen können:
$ rake some:task arg1 arg2
Einfach, oder? (Nee!)
Rake interpretiert arg1
und arg2
als Aufgaben und versucht, sie auszuführen. Also brechen wir einfach ab, bevor es passiert.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Nimm das, Klammern!
Haftungsausschluss : Ich wollte dies in einem ziemlich kleinen Haustierprojekt tun können. Nicht für die Verwendung in der "realen Welt" vorgesehen, da Sie nicht mehr in der Lage sind, Rechenaufgaben (dh rake task1 task2 task3
) zu verketten . IMO nicht wert. Benutze einfach das Hässliche rake task[arg1,arg2]
.
_, arg1, arg2 = ARGV
da das erste Argument der Name der Rechenaufgabe war. Aber das exit
ist ein ordentlicher Trick.
rake task[arg1,arg2] && rake task2 && rake task3
Ich bin mir nicht sicher, ob das weniger hässlich ist als rake task[arg1,arg2] task2 task3
. Wahrscheinlich weniger effizient.
_, *args = ARGV
ist perfekt, um alle nachfolgenden Argumente zu erfassen! Tausend Dank!
Ich verwende ein reguläres Ruby-Argument in der Rake-Datei:
DB = ARGV[1]
Dann lösche ich die Rake-Tasks am Ende der Datei (da Rake nach einer Task sucht, die auf diesem Argumentnamen basiert).
task :database_name1
task :database_name2
Befehlszeile:
rake mytask db_name
das fühlt sich für mich sauberer an als die var = foo ENV var und die task args [blah, blah2] lösungen.
Der Stub ist ein wenig ruckelig, aber nicht schlecht, wenn Sie nur ein paar Umgebungen haben, die einmalig eingerichtet sind
dup
am Ende: db = ARGV [1] .dup
db = ARGV[1].dup unless ARGV[1].nil?
, um eine Ausnahme vom Duping einer Null zu verhindern.
Die Möglichkeiten, Argumente zu übergeben, sind in der obigen Antwort korrekt. Um jedoch eine Rechenaufgabe mit Argumenten auszuführen, ist eine neuere technische Version von Schienen mit einer kleinen Technik verbunden
Es funktioniert mit Rake "Namespace: Taskname ['Argument1']"
Beachten Sie die invertierten Anführungszeichen beim Ausführen der Aufgabe über die Befehlszeile.
Um Argumente an die Standardaufgabe zu übergeben, können Sie Folgendes tun. Sagen Sie zum Beispiel "Version" ist Ihr Argument:
task :default, [:version] => [:build]
task :build, :version do |t,args|
version = args[:version]
puts version ? "version is #{version}" : "no version passed"
end
Dann können Sie es so nennen:
$ rake
no version passed
oder
$ rake default[3.2.1]
version is 3.2.1
oder
$ rake build[3.2.1]
version is 3.2.1
Ich habe jedoch keine Möglichkeit gefunden, die Angabe des Aufgabennamens (Standard oder Build) bei der Übergabe von Argumenten zu vermeiden. Würde gerne hören, wenn jemand einen Weg kennt.
Ich mag die "Querystring" -Syntax für die Übergabe von Argumenten, insbesondere wenn viele Argumente übergeben werden müssen.
Beispiel:
rake "mytask[width=10&height=20]"
Der "Querystring" ist:
width=10&height=20
Warnung: Beachten Sie, dass die Syntax rake "mytask[foo=bar]"
und NICHT ist rake mytask["foo=bar"]
Wenn Rack::Utils.parse_nested_query
wir innerhalb der Rechenaufgabe mit analysieren , erhalten wir ein Hash
:
=> {"width"=>"10", "height"=>"20"}
(Das Coole ist, dass Sie Hashes und Arrays übergeben können, mehr unten)
So erreichen Sie das:
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
Hier ist ein erweitertes Beispiel, das ich mit Rails in meinem Juwel " delay_job_active_record_threaded" verwende :
bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"
Auf die gleiche Weise wie oben analysiert, mit einer Umgebungsabhängigkeit (um die Rails-Umgebung zu laden)
namespace :dj do
task :start, [ :args_expr ] => :environment do |t, args|
# defaults here...
options = Rack::Utils.parse_nested_query(args[:args_expr])
end
end
Gibt Folgendes an options
=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}
Wenn Sie sich nicht die Mühe machen können, sich daran zu erinnern, welche Argumentposition für was ist, und Sie möchten so etwas wie einen Ruby-Argument-Hash tun. Sie können ein Argument verwenden, um eine Zeichenfolge zu übergeben und diese Zeichenfolge dann in einen Options-Hash umzuwandeln.
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
Und auf der Kommandozeile erhalten Sie.
$ 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
Die meisten der oben beschriebenen Methoden haben bei mir nicht funktioniert, möglicherweise sind sie in den neueren Versionen veraltet. Die aktuelle Anleitung finden Sie hier: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks
Eine Kopie zum Kopieren und Einfügen aus dem Handbuch finden Sie hier:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
Rufen Sie es so auf
bin/rake "task_name[value 1]" # entire argument string should be quoted
So führen Sie Rechenaufgaben mit traditionellem Argumentationsstil aus:
rake task arg1 arg2
Und dann benutze:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Fügen Sie folgenden Patch Rake Gem hinzu:
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
Während Sie Parameter übergeben, ist es besser, eine Eingabedatei zu verwenden. Dies kann ein Excel-JSON oder was auch immer Sie benötigen, und von dort aus lesen Sie die Datenstruktur und Variablen, die Sie benötigen, einschließlich des Variablennamens, wie es erforderlich ist. Das Lesen einer Datei kann die folgende Struktur haben.
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