2008-08-06 15 views
49

У меня есть Rakefile с задачей Рек, что я обычно называю из командной строки:Как запустить задачи Rake в скрипте Ruby?

rake blog:post Title 

Я хотел бы написать сценарий Ruby, который вызывает, что Rake задача несколько раз, но единственное решение, я вижу (outticks) или system.

Каков правильный способ сделать это?

ответ

43

из 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

С Rails 3.1 рек/rdoctask является устаревшим и задачи/рельсы отсутствует. Вышеизложенное прекрасно работает только с первым требованием. – jwadsack 2012-01-09 21:07:44

+0

Для изменения stdout я предлагаю сохранить исходный поток через `# dup`, затем` # reopen` в `Tempfile`, который читается после повторного открытия оригинала. Простое назначение `$ stdout` не будет работать, если задача использует константу` STDOUT` или запускает внешнюю программу. – Kelvin 2013-03-06 22:29:06

+0

Имейте в виду, что `rake_require` всегда соединяет заданный путь с каждым путем из массива` $ LOAD_PATH` и проверяет наличие файла. Таким образом, первым аргументом должен быть ** относительный путь **. Он будет относиться как относительный, даже если он содержит ведущую косую черту (или обратную косую черту в системах, отличных от Unix). – siefca 2013-12-04 15:55:06

13

Вы можете использовать invoke и reenable для выполнения задачи во второй раз.

Ваш пример вызова rake blog:post Title, похоже, имеет параметр. Этот параметр может быть использован в качестве параметра в invoke:

Пример:

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

Пожалуйста, замените mytask с blog:post и вместо определения задачи вы можете require ваш rakefile.

Это решение напишет результат на stdout - но вы не упомянули, что хотите подавить вывод.


Интересный эксперимент:

Вы можете вызвать reenable также в определении задач. Это позволяет выполнить задачу.

Пример:

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

Результат (протестирована с рейк 10.4.2):

"called mytask (one)" 
"called mytask (two)" 
17

Это работает с Rake версии 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 

Как сказал Кнут , используйте reenable, если вы хотите вызывать несколько раз.

1

В сценарии с Rails загружен (например 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') 

 Смежные вопросы

  • Нет связанных вопросов^_^