2008-08-06 24 views
49

Mam Rakefile z zadania Rake, że ja normalnie wywołać z linii poleceń:Jak uruchomić zadania Rake w skrypcie Ruby?

rake blog:post Title 

Chciałbym napisać skrypt Ruby, który wywołuje tego zadania Rake wiele razy, ale tylko rozwiązanie widzę wyławia się za pomocą `` (backticks) lub system.

Co to jest właściwy sposób?

Odpowiedz

43

z 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

z szyn 3,1 grabie/rdoctask jest przestarzała i zadania/szyn nie ma. Powyższe działa dobrze tylko z pierwszym wymaganiem. – jwadsack

+0

Aby zmienić standardowe wyjście, sugeruję zapisanie oryginalnego strumienia przez '# dup', następnie # # ponowne otwarcie' do 'Tempfile', który jest czytany po ponownym otwarciu do oryginału. Samo przypisanie '$ stdout' nie będzie działać, jeśli zadanie używa stałej' STDOUT' lub uruchamia zewnętrzny program. – Kelvin

+0

Należy pamiętać, że 'rake_require' zawsze łączy daną ścieżkę z każdą ścieżką z tablicy' $ LOAD_PATH' i sprawdza istnienie pliku. Zatem pierwszym argumentem powinna być ** względna ścieżka **. Będzie traktowany jako względny, nawet jeśli zawiera wiodący ukośnik (lub ukośnik odwrotny w systemach innych niż systemy uniksowe). – siefca

13

Można użyć invoke i reenable wykonać zadanie po raz drugi.

Twój przykładowy numer rake blog:post Title wydaje się mieć parametr. Parametr ten może być używany jako parametr w invoke:

Przykład:

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') 

Proszę wymienić mytask z blog:post i zamiast definicja zadanie można require swoją Rakefile.

To rozwiązanie zapisze wynik na stdout - ale nie wspomniałeś, że chcesz pominąć wyjście.


ciekawy eksperyment:

można nazwać reenable również wewnątrz definicji zadań. Dzięki temu zadanie może zostać ponownie włączone.

przykład:

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') 

Wynik (testowane nachylenia 10.4.2)

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

to nie działa dla zadań wewnątrz klejnotów –

+0

@JasonFB Czy masz przykład, dlaczego nie? – knut

+0

@JasonFB Zobacz także moją zredagowaną odpowiedź. Być może jest to alternatywa dla twojego problemu .. – knut

17

działa z Rake wersja 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 

jako Knut , użyj reenable, jeśli chcesz wywołać wiele razy.

+1

to nie działa dla zadań wewnątrz klejnotów –

+0

Witam @JasonFB, możesz uzyskać dostęp do klejnotu z czymś takim jak 'app.add_import" # {Gem :: Specification.find_by_name ('statesman ") .gem_dir} /lib/tasks/statesman.rake" ' – spikeheap

1

W scenariuszu z szynami ładowane (np 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')