Capistrano と Rake の比較

実は最初 Capistrano の記事を書いたときは大真面目に一部 Rake の機能を使っていると思っていた。コードも読んでなかったし、task 定義の構文が似ているというだけでそう思い込んでしまった。

でも実は全然ベツモノだったことにあとで気づいた。とは言え似ているのは実際に似ているので、自分の気づいた似ている点、同じように使える点、違っている点をちょっと挙げてみようと思う。

あくまで task 定義、実行時に使えるところの話で、中身の違いについてはほとんど言及していないのであしからず。

似ている点

  • task do; end によるタスク定義
    • まぁこれが基本ですね
  • namespace do; end による namespace 定義
  • コマンドラインオプションもよく似ている

異なる点

コマンド名、デフォルトの定義ファイル名が違う

ツールコマンドデフォルトの定義ファイル名
RakerakeRakefile
CapistranocapCapfile

default/file/directory task がない

実は自分は Rake をビルドツールとして使っていないためか、この default task の動作はイマイチ馴染めずにいた。Capistrano はこれがなくなっただけですっきりした感じで、好感を持ったりしている。

依存タスクの定義方法

rake では

task TASK => depends do
  ...
end

という形で depends の位置に依存 task を書くことができ、file task, directory task ではこの機能を使うことで関係するファイル群を簡潔に記述することができる。しかし Capistrano ではこういった書き方はできない1。Capistrano では以下のように依存 task ではなく、trigger に別の task を登録していく形になっている。

task :taskA do
  ...
end

task :taskB do
  ...
end
before :taskA, :taskB

before だけでなくいろいろ trigger があり、これらの trigger 用のメソッドに task を追加していく。最初ちょっと面倒だなと思ったが、これはこれで読みやすく、すぐに慣れることができた。

接続先サーバの記述

Rake で依存タスクを書く位置には接続先のサーバ群を記述することができるようになっている。

task :taskA, :roles => :ROLENAME do
  ...
end

という形で記述する。:roles に書ける role は

role :ROLENAME, hostname1, hostname2, ...

という形で定義しておく。

task の呼び出し

Rake の場合は他の task の呼び出しは depends に書く以外に方法がない。しかし Capistrano では他の task をメソッドと同じように呼ぶことができる。

まぁ凝った処理をする場合は task ではなく独自に module や class を定義していくことになっていくだろうから、この機能はあまり使わないと思うけど。

スコープ

Rake の場合は「地の文」も namespace も task も Global なというか main のメソッドなので、例えばそこで定義した変数は main に属しており、それが分かっていれば値のやりとりはそれほど大きな苦労がない。

しかし Capistrano の場合は Rake で main に当たる部分が Capistrano::Configuration となり、namespace も task もすべて別々の階層に属すオブジェクトとなっている。2そこで Capistrano では set というメソッドを使って独自に変数を定義し、fecth でその値を取り出すことで、task 間で変数をやり取りできるようにしている。

set :var, val
fetch :var

Capistrano を Rake のように使う

以下の点に気をつければ Capistrano と Rake の違いをあまり気にせず使える。気をつけてほしいのは、Capistrano があれば Rake なんて要らないぜ!ということを言いたいわけではないということ。あくまで、この場合は Rake、この場合は Capistrano、と使い分けを考えなくても、この辺だけ意識すれば Capistrano だけでもある程度イケるよ、ということで書いている。

接続先サーバを記述しない

task :TASKNAME, :roles => :ROLE do
  ...
end

ではなく

task :TASKNAME do
  ...
end

で書いていく。

run メソッドを使わない

run メソッドはリモートのサーバにログインして実行するためのものなので、

task :TASKNAME do
  system()
end

あるいは

task :TASKNAME do
  Rubyコード
end

だけで書くようにすればリモートサーバへのログインなしに task を実行できる。

  1. というか Capistrano ではこの部分は実行サーバの定義に使われている。 

  2. ドキュメントはそれほど多くない Capistrano だが、RDoc を読んでいくとどのオブジェクトにどのような役割が割り当てられているのかはだいたい分かるようになっている。 

More