Rackあそび

前回のRuby勉強会@関西 #26で話題騒然だったRackというツールを使って,very シンプルなtwitterビューアを書いてみました.

Rack?

RackはWebサーバとWebアプリケーションフレームワークの間の橋渡しをするRubyで書かれたソフトウェアです.WebサーバとWebアプリケーションフレームワークがRackのためインターフェースをもっていれば,簡単に組み合わせることができます.たとえば,あるWebアプリケーションをRackに対応させておけば,MongrelやWEBrickやFastCGIに同時に対応できるようになります.

 WebServers                 WAFs
-----------               -----------
| Mongrel |               | Ramaze  |
| WEBrick |               | Coset   |
| FastCGI |  <=> Rack <=> | Merb    |
| Thin    |               | Sinatra |
| ...     |               | ...     |
-----------               -----------
# Rackを真ん中にはさむことでどのような組み合わせも可能

より,くわしい話はRack を使って Web サーバで統一されたインターフェイスの利用するが良い感じです.

PerlでいうとHTTP::Engineが同じようなモジュールになるのかな?

Racktter

Rackをとりあえず使ってみるために,veryシンプルなtwitterクライアントを作ってみました.自分のTimelinesを表示するだけの簡単なお仕事しかしませんが,携帯で見るときにはシンプルでいいかもしれません.

Rackの上で動作するWebアプリケーションはインターフェースとしてcallというインスタンスメソッドを実装する必要があります.*1callメソッドの最後でRack::Responseオブジェクト返せばそれがWebサーバに渡されます.

require 'rubygems'
require 'twitter'
require 'yaml'
require 'erb'

class Racktter
  def initialize
    # twitterクライアントを仕込む
    config = YAML.load(open("config.yaml").read)
    @twitter = Twitter::Client.new(config)
  end

  def call(env)
    res = Rack::Response.new
    
    # timelineを取得
    timelines = @twitter.timeline_for(:friend) 
    
    # viewに書き込む
    erb = ERB.new(template)
    res.write erb.result(binding)
    
    res.finish
  end

  def template
    return <<-END
    <html>
    <body>
    <ul>
      <% timelines.each do |t| %>
        <li>
          <%= t.%h>:
          <%= t.text %> 
        </li>
      <% end %>
    </ul>
    </body>
    </html>
    END
  end
end

こうやって作ったClassをロードするためにruファイルを作ります.

require 'racktter'
map "/" do
  run Racktter.new
end

さきほど作ったクラスのインスタンスをrunでRackに渡しています.ここまでできたら,これをWebサーバを指定して起動します.rackupというコマンドラインツールがあるので,

$ rackup -s mongrel -p 3003 racktter.ru

とすると,MongrelをWebサーバとして先ほどつくったWebアプリケーションが動作するようになります.非常にお手軽ですね.

まとめ

とりあえず,WebサーバとWebアプリケーションフレームワークを自由自在に組み合わせるためのソフトウェア,Rackを利用してみました.本来は,ひとつのWebアプリケーションをいろんなサーバで簡単に利用するためのソフトウェアだと思うのですが,実際やってみるとさくっとWebアプリケーションを作って動かすのに使うのにも悪くない感じです.

Ruby勉強会でストヤンさんもおっしゃてたのですが,こういう単機能で良くできたツールはいろいろな組み合わせ方が発見できておもしろいですね.

*1:なので,実はProcのインスタンスを渡してもOK.very cool.