2008-08-06 66 views
49

Tôi có một Rakefile với một nhiệm vụ Rake mà tôi thường gọi từ dòng lệnh:Làm cách nào để chạy các tác vụ Rake trong tập lệnh Ruby?

rake blog:post Title 

Tôi muốn viết một kịch bản của Ruby mà các cuộc gọi mà nhiệm vụ Rake nhiều lần, nhưng giải pháp duy nhất tôi nhìn thấy đang bắn phá bằng cách sử dụng `` (backticks) hoặc system.

Cách thích hợp để thực hiện việc này là gì?

Trả lời

43

từ 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

Với Rails 3.1 rake/rdoctask đã bị phản đối và nhiệm vụ/đường ray là mất tích. Các công trình trên chỉ tốt với tuyên bố yêu cầu đầu tiên. – jwadsack

+0

Để thay đổi stdout, tôi khuyên bạn nên lưu luồng gốc thông qua '# dup', sau đó' # reopen' thành 'Tempfile' được đọc sau khi mở lại bản gốc. Chỉ gán '$ stdout' sẽ không hoạt động nếu tác vụ sử dụng hằng số' STDOUT', hoặc chạy một chương trình bên ngoài. – Kelvin

+0

Lưu ý rằng 'rake_require' luôn tham gia đường dẫn đã cho với mỗi đường dẫn từ mảng' $ LOAD_PATH' và kiểm tra sự tồn tại của một tệp. Vì vậy, đối số đầu tiên phải là ** đường dẫn tương đối **. Nó sẽ được coi là tương đối ngay cả khi nó có chứa dấu gạch chéo hàng đầu (hoặc dấu gạch chéo ngược trên các hệ thống không phải Unix). – siefca

13

Bạn có thể sử dụng invokereenable để thực hiện nhiệm vụ một lần thứ hai.

Cuộc gọi mẫu của bạn rake blog:post Title dường như có tham số. Tham số này có thể được sử dụng như một tham số trong invoke:

Ví dụ:

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

Hãy thay thế mytask với blog:post và thay vào đó định nghĩa công việc bạn có thể require rakefile của bạn.

Giải pháp này sẽ ghi kết quả vào thiết bị xuất chuẩn - nhưng bạn không đề cập đến, mà bạn muốn chặn đầu ra.


Thú vị thí nghiệm:

Bạn có thể gọi reenable cũng bên trong định nghĩa nhiệm vụ. Điều này cho phép một nhiệm vụ có thể tự bật lại.

Ví dụ:

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

Kết quả (thử nghiệm với cào 10.4.2):

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

điều này không làm việc cho các nhiệm vụ bên trong của Gems –

+0

@JasonFB Bạn có một ví dụ tại sao không? – knut

+0

@JasonFB Xem thêm câu trả lời đã chỉnh sửa của tôi. Có lẽ đây là một thay thế cho vấn đề của bạn .. – knut

17

này làm việc với phiên bản 10.0.3 Rake:

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 

Như Knut nói , sử dụng reenable nếu bạn muốn gọi nhiều lần.

+1

điều này không làm việc cho các nhiệm vụ bên trong của Gems –

+0

Hi @ JasonFB, bạn có thể truy cập gem với một cái gì đó như 'app.add_import" # {Gem :: Specification.find_by_name ('statesman ') .gem_dir} /lib/tasks/statesman.rake "' – spikeheap

1

Trong một kịch bản với Rails nạp (ví dụ 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') 
Các vấn đề liên quan