Sinatraが使いやすいので勝手に宣伝してみる

 これまで、ウェブアプリを作るような仕事ではRailsを使ってきたのだが、簡単なCGI、特にバックエンドサーバの設定や状態管理などを行うだけでDBが必要ないようなケースとかは、Railsではややオーバースペックである。RailsはDBへのコネクタなしで動かす方法が分からなかった(たぶん存在するんだとは思いますが…)り、いちいちコントローラを分けて書くのはちっさいアプリだと面倒くさかったりして、フィットしない場合も多い。
 で、Rails以外のフレームワークということで、最近はSinatraを使い始めている。開発せずともわかるメリットとして、Sinatra

  • Pure Rubyで動くのでインストールが楽
  • sinatraとrackを同梱してしまえばrubygemsなしで動くのでインストールが楽
  • CGIでもまともな速度で動く

 というようなものがある。
 インストールが簡単なのは非常に重要である。インストールが簡単だとインストールマニュアルも短くできる。CGIで動くのも魅力的で、「とにかくCGIを置いてパーミッションを変えれば動くんですよ」というと、普通の人の抵抗感を減ずることができる。また、「CGIでも」動くものなので、大量にアクセスを捌きたいのであれば、thinやらpassengerやらを使えば秒間数百アクセスぐらいは普通に捌ける。
 コードを書いて分かるSinatraの魅力はコードが非常に短いことで、例えば、トップにアクセスして"Hello World!"を表示するだけなら以下の5行で書ける。

require 'rubygems'
require 'sinatra'
get '/' do
  "Hello World!"
end

 requireを除けば3行だ。
 getはHTTPのGETメソッドに対する応答であること、そのパラメータである'/'はトップへのアクセスであることを示す。つまり、トップへのアクセスがきたら"Hello World"という文字列を返す。基本的に、ブロックが返す文字列がそのまま表示される。テンプレートが使いたければ、補助メソッドで明示的にテンプレートの呼び出しを行う。テンプレート呼び出しは以下のような感じになる。

  erb :index

 これでviews/index.erbが呼ばれる。viewsとかのディレクトリ名は変更できる。ディレクトリ階層を作りたい場合は

  erb :"foobar/index"

 と、文字列にコロンをつけてシンボル化する。単なる文字列だと受け付けてくれなかったような気がする。
 Sinatraがいいなと思うのは細かいところで気が利いている点で、例えばステータスコードを変更したければstatusメソッドを呼び出すだけで良いし、Content-Typeを指定したければcontent_typeメソッドを呼び出せばいい。例えば、CSVファイルのエクスポート機能をつけたかったら以下のようなコードになる。

if found
  content_type "text/csv"
  attachment "text.csv"
  return data
else
  status 404
  return "Data Not Found"
end

 attachmentというメソッドがファイル名を決める。あと、書いてから気づいたけど、この場合だとsend_fileを使った方がいいかもしれない。
 別のページにリダイレクトしたい時はredirectメソッドでredirectがかけられるが、例えば、エラー処理で一つ前のページに戻る、なんていう処理はよくある。そういうのは

redirect back

 と書けば良かったりする。backメソッドはリファラを返すので、結果として一つ前のページに戻れる。
 大規模なウェブアプリを書くときには今でもRailsかMerbあたりを使うだろうけど、せいぜい10画面程度の小さなアプリなら、もうSinatraでいいかなーと感じる。おすすめです。
 最後にたぶんもう数週間しか役に立たない豆知識も書いておく。実際にCGIで動かそうとすると、現在の最新版の0.9.2はパッチを当てなければいけない。"Errno::ESPIPE: Illegal seek" with CGI + Sinatraあたりを参照。もう修正されてるので、次のリリースなら普通に動くはず。
 さらにおまけで豆知識。

  • 0.9.2だとwebrickで動かない
  • 自動再読み込みの機能はなくなったので開発時にはshotgunを使うべきなんだけど、shotgunはパースエラーに弱い気がするのでCGIで開発した方が良いかも