1. ホーム
  2. スクリプト・コラム
  3. ルビートピックス

Rubyでタスクビルダーのrakeを使い始める

2022-01-31 05:24:23

Rake入門

RakeとはRuby Makeの略で、rubyで開発されたコードビルドツールです。

しかし、なぜRubyにRakeが必要なのでしょうか?

    Rubyのコードはコンパイルする必要がないから、Rakeは必要ないのでは?Rakeには別の目的があることがわかりました。タスク管理ツールとして使うのです...。これには2つの利点があります。

1. スクリプトをタスクとして作成し、実行する

   もちろん、自動的に実行させたいタスクはすべてスクリプトで作成することができます。しかし、大規模なアプリケーションでは、データベースのマイグレーション (Railsのdb:migrateタスクのようなもの)、キャッシュのフラッシュ、コードのメンテナンスなど、ほとんどの場合スクリプトを書く必要があります。それぞれのタスクに対して、いくつものスクリプトを書く必要があり、管理が煩雑になります。まあ、それらをタスクとしてまとめて整理することで、管理はかなり楽になるのですが。

2. タスク間の依存関係の追跡と管理

Rakeは、タスク間の依存関係を簡単に管理する方法も提供しています。例えば、"migrate" タスクと "schema:dump" タスクが両方とも "connect_to_database" タスクに依存する場合、"migrate" タスクが呼ばれる前に "connect _to_database" タスクは実行されることになります。

本題に入りましょう。つまり、Rakeでどのようにタスクをスクリプト化するかということです。

逐次実行

Rakeでタスクを定義した後、例えば毎朝起きたときに行うルーチンワークのように、実行する順番を指定することができます。
1. 目覚まし時計をオフにする
2.リフレッシュする
3.コーヒーを入れる
4. 犬の散歩
上記のうちいくつかは、Rakefileに次のように記述されています。

 task :turn_off_alarm do
  would have liked 5 more minutes, though."
 end

 task :groom_myself do
  puts "Brushed teeth."
  puts "Showered."
  puts "Shaved."
 end

 task :make_coffee do
  cups = ENV["COFFEE_CUPS"] || 2
  puts "Made #{cups} cups of coffee. shakes are gone."
 end

 task :walk_dog do
  puts "Dog walked."
 " end

 task :ready_for_the_day => [:turn_off_alarm, :groom_myself, :make_coffee, :walk_dog] do
  puts "Ready for the day!"
 end




rake ready_for_the_day でタスクを実行すると、すべてのタスクが意図した順序で実行されていることが確認できます。

 Turned off alarm. would have liked 5 more minutes, though.
 Brushed teeth.
 Showered.
 Shaved.
 Made 5 cups of coffee.
 Dog walked.
 Ready for the day!




また、rake make_coffee COFFEE_CUPS=5 で、コマンド内の変数に値を代入することも可能です。

名前空間

このようにタスクを定義するのはいいのですが、それ以外に仕事関係や交通関係などの定義が必要な場合、すべてのタスクを混在させるのは明らかに不適切です。結局のところ、それらは起きるために行うルーチンワークで、他にやることはないわけですから。

名前空間は、Railsでrake db:migrateのようなタスクを定義するのに役立ち、以下のように名前空間内のコードブロックに上記のタスクを含めることによって、物事の間に明確な境界線を引くことができます。

 namespace :morning do
  task :turn_of_alarm
  ....
 end


今回は、rake COFFEE_CUPS=3 morning:ready_for_the_day という呼び出しコマンドを少し変更する必要があります。これは rails で rake タスクが呼び出される方法と似ていませんか?

デフォルトのタスク

上記の設定で、もし詳細なタスク名を書き忘れたり書きたくなかったりした場合、rakeを直接実行するとどうなるでしょうか。このような可能性があるため、このような落とし穴をなくす必要があり、以下のようにデフォルトの既定タスクを設定することで対応できます。

 task :default => 'morning:turn_off_alarm'




rakeコマンドを直接実行すると、デフォルトのアクションが実行され、アラームをオフにするのに役立ちます。

タスクの記述

タスクが多くなればなるほど、管理上の問題が表面化します。タスクを分類し、それぞれのタスクの目的や機能を示すには、名前空間だけでなく、文書クラスのサポートが必要ですので、タスクをdescで記述してみるとよいでしょう。

 ...
 desc "Make coffee"
 task :make_coffee do
  cups = ENV["COFFEE_CUPS"] || 2
  puts "Made #{cups} cups of coffee. shakes are gone."
 end
 ...




上記の説明は、ドキュメントだけでなく、rake -T を使って各タスクが何をするのかきれいに見ることができます。rake -T の出力はアルファベット順になっています。

 rake morning:make_coffee # Make coffee




タスクの呼び出し

Rakeでは、タスク間で相互に呼び出すこともできます。たとえば、次のコードでは、午後にもコーヒーを飲みたいので、定義を繰り返すのではなく、午前中のbrewを使って、一杯飲むだけです。

namespace :afternoon do
  task :make_coffee do
   Rake::Task['morning:make_coffee'].invoke
   puts "Ready for the rest of the day!"
  end
 end




Rakeスクリプト

まずは、次のような簡単な例から見てみましょう。

あなたが火星のメンバーだとすると、それらの古いバージョン、すなわちYan'er Hu Runなど、週末にあなたは鍋を再生するために車の車側、および集団PCに行くことを計画しています。このような状況に対して、ヒッチハイクで車を探す、魚を焼く、ネットカフェPCの3つのタスクを自分で作成する必要があります。vimを使ってrakefileというファイルを作り(注:Rakeは現在のパスでrakefile, rakefile, RakeFile.rb, rakefile.rbファイルを探します)、次のコードをタイプして入力します。

desc "Task 1 -- Hitch a ride to the busboy"# This is said to be a chore because it's so far away 
task :busboy do 
puts "Found frustrated man" 
end 
 
desc "Task 2 -- grill fish" 
task :bitchfish do 
puts "Boss, bake nine pounds of fish first" 
end 
 
desc "Task 3 -- Internet Cafe PC" 
task :pc do 
puts "I choose the middle road" 
end 



コマンドラインツールを開き、このファイルがあるディレクトリに移動して、以下のようなコマンドを実行します。

D:\work>rake busboy 
(in D:/work) 
Found frustrated man 
 
D:\work>rake bitchfish 
(in D:/work) 
Boss, bake nine pounds of fish first 
 
D:\work\ruby_works\ruby_book>rake laundry 
(in D:/work) 
I choose the middle way 




(注:テキスト部分は論理的ではなく、純粋に楽しむためのものです...)

分析する。

上の段落を読んで、もうやり方はわかったと思うのですが...。では、より理解を深めるために基本的なことを紹介します。上のコードからわかるように、このファイルには3つのタスクが定義されており、descはその下に定義されているタスクを記述するためにRakeが定義したメソッドです。この説明はRake --tasks (またはRake -T)コマンドを使用したときに画面に出力されます。

D:\work>rake --tasks 
(in D:/work) 
rake bitchfish #task2 -- grilled fish 
rake busboy #mission1 -- hitchhike to the bus (this is supposedly a chore because it's so far away) 
rake pc mission 3 -- internet cafe pc 




タスクは、Rakeの最も重要なメソッドです。そのメソッドの定義は、task(args, &block)です。タスク本体はブロックであり、この場合は単純にやりたい作業を出力します。重要なのは、次のコードです。

puts "Found frustrated man" 




は全く普通のRubyの文であり、putsはRubyで出力を行うための一般的な方法である。このように、RakeタスクはRubyの力をフルに使うことができるので、とても強力です。

ゴーゴーゴーゴー。

次に、依存関係を追加します。

明らかに、私たちが定義したタスクにおいて、"焼き魚"は"車への乗り物"に依存しています(他の場所で焼き魚があるかどうかは分かりませんが、とにかくそこが重要なのです)。そこで、この依存関係をタスク定義に追加する必要があり、修正したファイルは次のようになります。

desc "Task 1 -- Hitch a ride to the bus" 
task :busboy do 
puts "Found frustrated man" 
end 
 
desc "task 2 -- grill fish" 
task :bitchfish => :busboy do 
puts "Boss, grill nine pounds of fish first" 
end 
 
desc "Task 3 -- Internet Cafe PC" 
task :pc do 
puts "I choose middle" 
end 



もう一度fish bakeタスクを実行すると、以下のような結果になります。

D:\work>rake bitchfish 
(in D:/work) 
Found the frustrated man 
Boss, grill nine pounds of fish first 


名前空間を追加します。

どんなプログラミング言語でもそうですが、たくさんの rake ファイルがあるとき、たくさんのタスクがあるとき、名前の衝突に気をつける必要があり、名前空間は自然な解決方法です。上記の3つのタスクのために、danという名前空間を定義することができます。

namespace :dan do 
desc "Task 1 -- Hitch a ride to the busboy" 
task :busboy do 
puts "Found frustrated man" 
end 
...... 
end 



もう一度rake -tasksを実行すると、以下のような結果になります。

D:\work >rake --tasks 
(in D:/work) 
rake dan:bitchfish # task 2 -- grill fish 
rake dan:pc # task 3 -- internet cafe pc 
rake dan:busboy # task 1 -- hitch a ride to the bus 




これで、rake dan:bitchfishを使用して、魚焼きタスクを開始する必要があります。
(ちなみに、rakefileではタスクを分類するために複数の名前空間を使用することができます)。

以上の2点を理解した上で、2つの具体的な例を見てみましょう。

1. タスクの中で別のタスクを呼び出す

タスクがたくさんあるとき、タスクの中に別のタスクを呼び出すことが必要になることがあります。例えば、今日しなければならない仕事をすべて「今日」という一つのタスクとして定義するとします。ファイルの先頭で今日のタスクを定義します。

desc "Today's task" 
task :today do 
Rake::Task["dan:bitchfish"].invoke 
Rake::Task["dan:pc"].invoke 
end 
 
namespace :dan do 
...... 
end 



このように、他のタスクを呼び出す方法は簡単で、ただ

Rake::Task["task_name"].invoke 



メソッドを使えば、うまくいきます。コマンドラインから rake today を起動すると、次のようになります。

D:\work >rake today 
(in D:/work) 
Found the frustrated man 
Boss, first grill nine pounds of fish 
I choose the middle 



2. デフォルトの割り当てです。

Rakeにデフォルトのタスクを追加して、Rakeコマンドで簡単に起動できるようにすることができます。上記のrakefileでは、以下の方法で"today"タスクをデフォルトタスクにすることができます。

task :default => [:today] 




そして、コマンドラインから直接 rake を呼び出すと、今日の rake と同じ出力が得られます。

これは rake タスクの簡単な定義で、以下は修正した rakefile の完全版です。

task :default => [:today] 
 
desc "Today's tasks" 
task :today do 
 Rake::Task["dan:bitchfish"].invoke 
 Rake::Task["dan:pc"].invoke 
end 
 
namesoace :dan do 
 desc "Task 1 -- hitchhike to the busboy (this is said to be a chore because it's so far away)" 
 task :busboy do 
  puts "found frustrated man" 
 end 
 
 desc "task 2 -- grill fish" 
 task :bitchfish do 
  puts "Boss, bake nine pounds of fish first" 
 end 
 
 desc "Task 3 -- Internet Cafe PC" 
 task :pc do 
  puts "I choose the middle road" 
 end 
end 



上記の2つの例を読んで、rakeタスクはすべて理解できたと推定される......。その他は、いくつかのコードガンです。ただ、遊んでみてください。