Ich habe eine Rake-Aufgabe, die einen Wert in mehrere Datenbanken einfügen muss.
Ich möchte diesen Wert in die Rake-Task von der Befehlszeile oder von einer anderen Rake-Task übergeben.
Wie kann ich das machen?
optionen und Abhängigkeiten müssen sich innerhalb von 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: Die Variable
task
ist das Task-Objekt. Es ist nicht sehr hilfreich, wenn Sie sich nicht mit Rake-Internals auskennen.
Schienen HINWEIS:
Wenn Sie die Task über Rails ausführen, laden Sie die Umgebung am besten vorab, indem Sie
=> [:environment]
hinzufügen. Dies ist eine Möglichkeit, abhängige -Tasks einzurichten.
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
Sie können formale Argumente in Rake angeben, indem Sie dem Task-Aufruf Symbolargumente hinzufügen. Zum Beispiel:
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
Dann von der Kommandozeile aus:
> rake my_task [1,2] Args waren: {: arg1 => "1",: arg2 => "2"} > rake "my_task [1, 2]" Args waren: {: arg1 => "1",: arg2 => "2"} > Rake invoke_my_task Args waren: {: arg1 => "1",: arg2 = > "2"} > Rechen invoke_my_task_2 Args waren: {: arg1 => 3,: arg2 => 4} > Rechen mit Vorbedingung [5,6] Args waren: {: arg1 => "5",: arg2 => "6"} > Rake with_defaults Args mit Standardwerten waren: {: arg1 =>: default_1,: arg2 =>: default_2} > rake with_defaults ['x', 'y'] Standardeinstellungen waren: {: arg1 => "x",: arg2 => "y"}
Wie im zweiten Beispiel gezeigt, müssen Sie die Anführungszeichen um den Zielnamen verwenden, wenn Sie Leerzeichen verwenden möchten, damit die Shell die Argumente an der Leiste nicht aufteilt.
Wenn Sie sich den Code in rake.rb anschauen, sieht es so aus, als würde Rake Taskstrings nicht analysieren, um Argumente für Voraussetzungen zu extrahieren. Daher können Sie task :t1 => "dep[1,2]"
nicht ausführen. Die einzige Möglichkeit, verschiedene Argumente für eine Voraussetzung anzugeben, besteht darin, sie explizit in der abhängigen Task-Aktion aufzurufen, wie in :invoke_my_task
und :invoke_my_task_2
.
Beachten Sie, dass bei einigen Shells (wie zsh) die Klammern nicht angezeigt werden müssen: rake my_task\['arg1'\]
Zusätzlich zur Antwort von kch (ich habe nicht gefunden, wie ich einen Kommentar dazu hinterlassen kann, sorry):
Sie müssen vor dem Befehl ENV
keine Variablen als rake
-Variablen angeben. Sie können sie einfach als gewöhnliche Befehlszeilenparameter wie folgt einstellen:
rake mytask var=foo
und greifen Sie als ENV-Variablen auf die Dateien aus Ihrer Rake-Datei zu:
p ENV['var'] # => "foo"
Wenn Sie benannte Argumente übergeben möchten (z. B. mit dem Standard OptionParser
), können Sie Folgendes verwenden:
$ rake user:create -- --user [email protected] --pass 123
beachten Sie den --
, der für das Umgehen von Standard-Rake-Argumenten erforderlich ist. Sollte mit Rake 0.9.x , <= 10.3.x arbeiten.
Der neuere Rake hat seine Analyse von --
geändert, und Sie müssen jetzt sicherstellen, dass er nicht an die OptionParser#parse
-Methode übergeben wird, beispielsweise mit 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
am Ende stellt sicher, dass die zusätzlichen Argumente nicht als Rake-Task interpretiert werden.
Auch die Verknüpfung für Argumente sollte funktionieren:
rake user:create -- -u [email protected] -p 123
Wenn Rake-Skripts so aussehen, ist es vielleicht an der Zeit, nach einem anderen Werkzeug zu suchen, mit dem dies einfach möglich ist.
Ich habe die Antwort auf diesen beiden Websites gefunden: Net Maniac und Aimred .
Sie benötigen eine Version> 0.8 des Rechen, um diese Technik zu verwenden
Die normale Rake-Aufgabenbeschreibung lautet wie folgt:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Um Argumente zu übergeben, machen Sie drei Dinge:
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 Task von der Befehlszeile aus aufzurufen, übergeben Sie die Argumente in [] s
rake task_name['Hello',4]
wird ausgegeben
Hello
Hello
Hello
Hello
wenn Sie diese Task von einer anderen Task aus aufrufen und 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 bricht:
task :caller => :task_name['hi',2]' do
puts 'In Caller'
end
Eine andere häufig verwendete Option ist das Übergeben von Umgebungsvariablen. In Ihrem Code lesen Sie sie über ENV['VAR']
und können sie direkt vor dem Befehl rake
übergeben, z
$ VAR=foo rake mytask
Eigentlich hat @Nick Desjardins perfekt geantwortet. Aber nur für die Bildung: Sie können den Dirty-Ansatz verwenden: ENV
-Argument
task :my_task do
myvar = ENV['myvar']
puts "myvar: #{myvar}"
end
rake my_task myvar=10
#=> myvar: 10
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
Ich wollte nur laufen können:
$ rake some:task arg1 arg2
Einfach, richtig? (Nee!)
Rake interpretiert arg1
und arg2
als Aufgaben und versucht sie auszuführen. Also brechen wir einfach ab, bevor es funktioniert.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Nimm das, Klammern!
Disclaimer : Ich wollte das in einem ziemlich kleinen Haustierprojekt machen. Nicht für die Verwendung in der "realen Welt" gedacht, da Sie die Möglichkeit verlieren, Rake-Aufgaben (d. H. rake task1 task2 task3
) zu verketten. IMO lohnt sich nicht. Verwenden Sie einfach den hässlichen rake task[arg1,arg2]
.
Ich benutze ein reguläres Ruby-Argument in der Rake-Datei:
DB = ARGV[1]
dann stub ich die Rake-Tasks am Ende der Datei aus (da Rake nach einer Aufgabe 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 aufgabe args [bla, blah2] lösungen.
der Stub ist ein wenig jenky, aber nicht schlecht, wenn Sie nur wenige Umgebungen haben, die einmalig sind
Die Möglichkeiten, Argumente zu übergeben, sind in der obigen Antwort richtig. Um eine Rake-Task mit Argumenten auszuführen, ist in der neueren Version von Rails jedoch eine geringe technische Funktionalität erforderlich
Es wird mit Rake "Namespace: Taskname ['Argument1']" arbeiten.
Beachten Sie die umgekehrten Anführungszeichen, wenn Sie die Task von der Befehlszeile aus ausführen.
Ich mag die "querystring" -Syntax für das Übergeben von Argumenten, insbesondere wenn viele Argumente übergeben werden müssen.
Beispiel:
rake "mytask[width=10&height=20]"
Die "Querzeichenfolge" lautet:
width=10&height=20
Warnung: Beachten Sie, dass die Syntax rake "mytask[foo=bar]"
ist und NICHTrake mytask["foo=bar"]
.
Wenn Sie die Rake-Task mit Rack::Utils.parse_nested_query
analysieren, erhalten Sie eine Hash
:
=> {"width"=>"10", "height"=>"20"}
(Die coole Sache ist, dass Sie Hashes und Arrays passieren 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 ein ausführlicheres Beispiel, das ich mit Rails in meinem delayed_job_active_record_threaded gem verwende:
bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"
Wird 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 in options
=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}
Um Argumente an die Standardaufgabe zu übergeben, können Sie Folgendes tun. Zum Beispiel sagen Sie "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 kannst du 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, bei der Übergabe von Argumenten die Angabe des Aufgabennamens (Standard oder Build) zu vermeiden. Würde gerne hören, wenn jemand einen Weg kennt.
Die meisten der oben beschriebenen Methoden haben bei mir nicht funktioniert, vielleicht sind sie in den neueren Versionen nicht mehr empfohlen .. Die aktuelle Anleitung finden Sie hier: http://guides.rubyonrails.org/command_line html # custom-rake-task
ein copy-and-paste aus dem Guide ist hier:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
Beschreibe es so
bin/rake "task_name[value 1]" # entire argument string should be quoted
Wenn Sie sich nicht die Mühe machen müssen, sich daran zu erinnern, welche Argumentposition für was gilt, und Sie möchten etwas wie einen Ruby-Argumenthash tun. Sie können ein Argument verwenden, um einen String zu übergeben und diesen String dann in einen Optionshash auszudehnen.
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 bekommst du.
$ 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
Rake-Tasks mit traditionellen Argumenten ausführen:
rake task arg1 arg2
Und dann verwenden Sie:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Fügen Sie den folgenden Rake-Edelstein 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