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
確かに動作している。
ということは、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/
にアクセスしてみる。
確かに Sinatra アプリも動作した。
完全な Rack アプリケーションになったということは、Rack Middleware の資産もそのまま使える。
目的に応じて、組み込む場所が選べる。
RAILS_ROOT/config.fu
Rails 本体よりも先にロードし、適用Application.config
(RAILS_ROOT/config/application.rb
)
Rails の通常のリクエスト処理に対して適用コントローラ
各コントローラで、filter
同様に適用
大きく進化した Rails3 だが、完全な Rack アプリケーションになったのはうれしい。