Rails3 における Rack

Written by @dr_taka_n at 2011/02/28 01:06 [, ]

Rails3 は完全な Rack アプリケーションになったと、ものの本では目を通していたが、実際に試していなかったので確認してみた。

$ rails new rails_in_rack
$ cd rails_in_rack

Rack 準拠のサーバは、Rack の決まりに従って、RAILS_ROOT/config.ru から読み込む。このファイルの中身を見てみると、

require ::File.expand_path('../config/environment',  __FILE__)
run RailsInRack::Application

RAILS_ROOT/config/environment.rb を読み込んだ後に、RailsInRack::Application を run している。

Rack のエントリポイントと同様になっている。

また、ルーティング先に指定するオブジェクトはただの Rack アプリとなっているとのこと。
(ルーティング処理も Rack のレイヤとなっているようだ。)

であれば、試してみる。

Rack アプリケーションは、call メソッドを実装していればよく、call メソッドは、リクエスト発生時に、環境変数(env)を引数に呼び出されるので、最後にレスポンスとなるインスタンスを結果として返す処理を書くだけとなる。

Proc オブジェクトで書けるので、直接ルーティング先に Rack アプリケーションを指定してみる。

RAILS_ROOT/config/routes.rb:

RailsInRack::Application.routes.draw do
  root :to => proc { |env| [200, {}, ['Hello! from proc app']] }
end

RAILS_ROOT/public/index.html を削除しておいて、サーバを起動して http://localhost:3000/ にアクセスしてみる。

$ rm public/index.html
$ rails s

rails-in-rack-1

確かに動作している。

ということは、Sinatra でも動作する。

RAILS_ROOT/Gemfile に以下を追加し、Bunder を実行する。

RAILS_ROOT/Gemfile:

gem 'sinatra'
$ bundle install

Sinatra アプリケーションを用意する。

RAILS_ROOT/lib/home_app.rb:

class HomeApp < Sinatra::Base
  get '/' do
    'Hello! from Sinatra'
  end
end

Rails3 からデフォルトでは RAILS_ROOT/lib 配下はロードパスに加えられなくなっている。 RAILS_ROOT/config/application.rb に以下を追加しておく。

RAILS_ROOT/config/application.rb:

module RailsInRack
  class Application < Rails::Application
  ...
    config.autoload_paths += Dir["#{config.root}/lib/**/"]
  ...
  en
end

ルーティングの呼び先を先ほど用意した Sinatra アプリに変更しておく。

RAILS_ROOT/config/routes.rb:

RailsInRack::Application.routes.draw do
  root :to => HomeApp
end

再度 http://localhost:3000/ にアクセスしてみる。

rails-in-rack-1

確かに Sinatra アプリも動作した。

完全な Rack アプリケーションになったということは、Rack Middleware の資産もそのまま使える。

目的に応じて、組み込む場所が選べる。

  • RAILS_ROOT/config.fu
    Rails 本体よりも先にロードし、適用
  • Application.config(RAILS_ROOT/config/application.rb)
    Rails の通常のリクエスト処理に対して適用
  • コントローラ
    各コントローラで、filter 同様に適用

大きく進化した Rails3 だが、完全な Rack アプリケーションになったのはうれしい。

blog comments powered by Disqus