2008-08-06 11 views
49

Ich habe einen Rakefile mit einem Rake-Aufgabe, die ich normalerweise von der Kommandozeile aufrufen würde:Wie führe ich Rake-Aufgaben in einem Ruby-Skript aus?

rake blog:post Title 

Ich möchte schreiben ein Ruby-Skript, das fordert, dass Rake Aufgabe mehrere Male, aber die einzige Lösung, die ich sehen Schälen mit `` (Backticks) oder system.

Was ist der richtige Weg?

Antwort

43

von timocracy.com:

require 'rake' 
require 'rake/rdoctask' 
require 'rake/testtask' 
require 'tasks/rails' 

def capture_stdout 
    s = StringIO.new 
    oldstdout = $stdout 
    $stdout = s 
    yield 
    s.string 
ensure 
    $stdout = oldstdout 
end 

Rake.application.rake_require '../../lib/tasks/metric_fetcher' 
results = capture_stdout {Rake.application['metric_fetcher'].invoke} 
+1

Mit Rails 3.1 der Rechen/rdoctask ist veraltet und Aufgaben/Schienen fehlt. Das obige funktioniert nur mit der ersten require-Anweisung. – jwadsack

+0

Zum Ändern der Standardausgabe empfehle ich, den ursprünglichen Stream über '# dup' zu speichern, und dann' # reopen' in eine 'Tempdatei', die nach dem erneuten Öffnen des Originals gelesen wird. Das bloße Zuweisen von '$ stdout' funktioniert nicht, wenn die Task die' STDOUT'-Konstante verwendet oder ein externes Programm ausführt. – Kelvin

+0

Beachten Sie, dass 'rake_require' immer den angegebenen Pfad mit jedem Pfad aus dem '$ LOAD_PATH'-Array verknüpft und auf das Vorhandensein einer Datei prüft. Das erste Argument sollte also ein ** relativer Pfad ** sein. Es wird als relativ behandelt, auch wenn es einen führenden Schrägstrich (oder umgekehrten Schrägstrich auf Nicht-Unix-Systemen) enthält. – siefca

13

können Sie verwenden invoke und reenable die Aufgabe ein zweites Mal auszuführen.

Ihr Beispiel Anruf rake blog:post Title scheint einen Parameter zu haben. Dieser Parameter kann in invoke als Parameter verwendet werden:

Beispiel:

require 'rake' 
task 'mytask', :title do |tsk, args| 
    p "called #{tsk} (#{args[:title]})" 
end 



Rake.application['mytask'].invoke('one') 
Rake.application['mytask'].reenable 
Rake.application['mytask'].invoke('two') 

Bitte ersetzen mytask mit blog:post und stattdessen die Aufgabendefinition können Sie Ihre Rakefile require.

Diese Lösung wird das Ergebnis auf stdout schreiben - aber Sie haben nicht erwähnt, dass Sie die Ausgabe unterdrücken möchten.


interessantes Experiment:

Sie können die reenable rufen auch in der Aufgabendefinition. Dies ermöglicht es einer Aufgabe, sich selbst wieder zu aktivieren.

Beispiel:

require 'rake' 
task 'mytask', :title do |tsk, args| 
    p "called #{tsk} (#{args[:title]})" 
    tsk.reenable #<-- HERE 
end 

Rake.application['mytask'].invoke('one') 
Rake.application['mytask'].invoke('two') 

Das Ergebnis (getestet mit Harke 10.4.2):

"called mytask (one)" 
"called mytask (two)" 
+0

dies funktioniert nicht für Aufgaben innerhalb von Gems –

+0

@JasonFB Haben Sie ein Beispiel warum nicht? – knut

+0

@JasonFB Siehe auch meine bearbeitete Antwort. Vielleicht ist dies eine Alternative für Ihr Problem .. – knut

17

Dies funktioniert mit Rake Version 10.0.3:

require 'rake' 
app = Rake.application 
app.init 
# do this as many times as needed 
app.add_import 'some/other/file.rake' 
# this loads the Rakefile and other imports 
app.load_rakefile 

app['sometask'].invoke 

Wie knut sagte , verwenden Sie reenable, wenn Sie mehrere Male aufrufen möchten.

+1

Dies funktioniert nicht für Aufgaben innerhalb von Gems –

+0

Hallo @JasonFB, können Sie den Edelstein mit etwas wie app.add_import # zugreifen {Gem :: Specification.find_by_name ('staatsman ') .gem_dir} /lib/tasks/statesman.rake "' – spikeheap

1

In einem Skript mit Rails geladen (z rails runner script.rb)

def rake(*tasks) 
    tasks.each do |task| 
    Rake.application[task].tap(&:invoke).tap(&:reenable) 
    end 
end 

rake('db:migrate', 'cache:clear', 'cache:warmup')