このガイドでは、RailsとRackの関係、Railsと他のRackコンポーネントとの関係について説明します。
このガイドの内容:
このガイドはRackのミドルウェア、urlマップ、Rack::Builder
といったRackのプロトコルや概念に関する実用的な知識があることを前提にしています。
Rackは、Rubyのウェブアプリケーションに対して、最小限でモジュール化されていて、応用の効くインターフェイスを提供します。RackはHTTPリクエストとレスポンスを可能なかぎり簡単な方法でラッピングすることで、ウェブサーバー、ウェブフレームワーク、その間に位置するソフトウェア (ミドルウェアと呼ばれています) のAPIを一つのメソッド呼び出しの形にまとめます。
Rackに関する解説はこのガイドの範疇を超えてしまいます。Rackに関する基本的な知識が足らない場合、下記のリソース を参照してください。
Rails.application
はRailsアプリケーションをRackアプリケーションとして実装したものです。Rackに準拠したWebサーバーで、Railsアプリケーションを提供するには、Rails.application
オブジェクトを使用する必要があります。
rails server
コマンドrails server
コマンドはRack::Server
のオブジェクトを作成し、ウェブサーバーを起動します。
rails server
コマンドは以下のようにして、Rack::Server
のオブジェクトを作成します。
Rails::Server.new.tap do |server| require APP_PATH Dir.chdir(Rails.application.root) server.start end
Rails::Server
クラスはRack::Server
クラスを継承しており、以下のようにしてRack::Server#start
を呼び出します。
class Server < ::Rack::Server def start ... super end end
また次のようにして、ミドルウェアを読み込みます。
def middleware middlewares = [] middlewares << [Rails::Rack::Debugger] if options[:debugger] middlewares << [::Rack::ContentLength] Hash.new(middlewares) end
Rails::Rack::Debugger
は主としてdevelopment環境で役に立ちます。読み込まれたミドルウェアの役割は下表のとおりです。
ミドルウェア | 役割 |
---|---|
Rails::Rack::Debugger |
デバッガを起動する |
Rack::ContentLength |
レスポンスのバイト数を計算し、HTTP Content-Length ヘッダーをセットする |
rackup
コマンドRailsのrails server
コマンドの代わりにrackup
コマンドを使用するときは、下記の内容をconfig.ru
に記述して、Railsアプリケーションのルートディレクトリに保存します。
# Rails.root/config.ru require ::File.expand_path('../config/environment', __FILE__) use Rails::Rack::Debugger use Rack::ContentLength run Rails.application
サーバーを起動します。
$ rackup config.ru
rackup
のオプションについて詳しく知りたいときは下記のようにします。
$ rackup --help
Action Dispatcher内部のコンポーネントの多くは、Rackのミドルウェアとして実装されています。Rails内外の様々なミドルウェアを結合して、完全なRailsのRackアプリケーションを作るために、Rails::Application
はActionDispatch::MiddlewareStack
を使用しています。
ActionDispatch::MiddlewareStack
はRack::Builder
のRails版ですが、Railsアプリケーションの要求を満たすために、より柔軟性があり、多機能なクラスになっています。
Railsにはミドルウェアスタックを調べるための便利なRakeタスクがあります。
$ bin/rake middleware
作成したばかりのRailsアプリケーションでは、以下のように出力されるはずです。
use Rack::Sendfile use ActionDispatch::Static use Rack::Lock use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000000029a0838> use Rack::Runtime use Rack::MethodOverride use ActionDispatch::RequestId use Rails::Rack::Logger use ActionDispatch::ShowExceptions use ActionDispatch::DebugExceptions use ActionDispatch::RemoteIp use ActionDispatch::Reloader use ActionDispatch::Callbacks use ActiveRecord::Migration::CheckPending use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache use ActionDispatch::Cookies use ActionDispatch::Session::CookieStore use ActionDispatch::Flash use ActionDispatch::ParamsParser use Rack::Head use Rack::ConditionalGet use Rack::ETag run Rails.application.routes
デフォルトのミドルウェア(とその他のうちいくつか)については Internal Middlewares を参照してください。
ミドルウェアスタックにミドルウェアを追加したり、削除したり、変更したりするにはapplication.rb
もしくは環境ごとのenvironments/<environment>.rb
ファイル内でconfig.middleware
をいじります。
次のメソッドを使用すると、ミドルウェアスタックに新しいミドルウェアを追加することができます。
config.middleware.use(new_middleware, args)
- ミドルウェアスタックの一番下に新しいミドルウェアを追加します。
config.middleware.insert_before(existing_middleware, new_middleware, args)
- (第一引数で)指定されたミドルウェアの前に新しいミドルウェアを追加します。
config.middleware.insert_after(existing_middleware, new_middleware, args)
- (第一引数で)指定されたミドルウェアの後に新しいミドルウェアを追加します。
# config/application.rb # Rack::BounceFaviconを一番最後に追加する config.middleware.use Rack::BounceFavicon # ActiveRecord::QueryCacheの後にLifo::Cacheを追加する # またLifo::Cacheに{ page_cache: false }を渡す config.middleware.insert_after ActiveRecord::QueryCache, Lifo::Cache, page_cache: false
config.middleware.swap
を使用することで、ミドルウェアスタック内のミドルウェアを交換できます。
# config/application.rb # ActionDispatch::ShowExceptionsをLifo::ShowExceptionsで置き換える config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
アプリケーションの設定に、下記のコードを追加してください。
# config/application.rb config.middleware.delete "Rack::Lock"
ミドルウェアスタックを調べると、Rack::Lock
が消えていることが分かります。
$ bin/rake middleware (in /Users/lifo/Rails/blog) use ActionDispatch::Static use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8> use Rack::Runtime ... run Rails.application.routes
セッション関連のミドルウェアを削除したいときは次のように書きます。
# config/application.rb config.middleware.delete "ActionDispatch::Cookies" config.middleware.delete "ActionDispatch::Session::CookieStore" config.middleware.delete "ActionDispatch::Flash"
ブラウザ関連のミドルウェアを削除するには次のように書きます。
# config/application.rb config.middleware.delete "Rack::MethodOverride"
Action Controllerの機能の多くはミドルウェアとして実装されています。以下のリストでそれぞれの役割を説明します。
Rack::Sendfile
config.action_dispatch.x_sendfile_header
オプション経由で設定を変更できます。ActionDispatch::Static
config.serve_static_assets
をfalse
にするとオフになります。Rack::Lock
env["rack.multithread"]
をfalse
に設定し、アプリケーションをMutexで包みます。ActiveSupport::Cache::Strategy::LocalCache::Middleware
Rack::Runtime
Rack::MethodOverride
params[:_method]
が存在するときに、(HTTPの)メソッドを上書きます。HTTPのPUTメソッド、DELETEメソッドを実現するためのミドルウェアです。ActionDispatch::RequestId
X-Request-Id
ヘッダーに設定します。ActionDispatch::Request#uuid
メソッドも同一のidを利用しています。Rails::Rack::Logger
ActionDispatch::ShowExceptions
ActionDispatch::DebugExceptions
ActionDispatch::RemoteIp
ActionDispatch::Reloader
ActionDispatch::Callbacks
ActiveRecord::Migration::CheckPending
ActiveRecord::PendingMigrationError
を発生さます。ActiveRecord::ConnectionAdapters::ConnectionManagement
env['rack.test']
が true
でない場合のみ返却が行われます。ActiveRecord::QueryCache
ActionDispatch::Cookies
ActionDispatch::Session::CookieStore
ActionDispatch::Flash
config.action_controller.session_store
に値が設定されている場合にのみ有効です。ActionDispatch::ParamsParser
params
を設定します。ActionDispatch::Head
GET
に変換して処理します。その上でbodyを空にしたレスポンスを返します(訳注: Rails4.0からはRack::Headを使うように変更されています)。Rack::ConditionalGet
GET
" (Conditional GET
) 機能を提供します。"条件付き GET
"が有効になっていると、リクエストされたページに変更がないときに空のbodyを返すようになります。Rack::ETag
これらのミドルウェアはいずれも、Rackのミドルウェアスタックに利用できます。
Railsガイドは GitHub の yasslab/railsguides.jp で管理・公開されております。本ガイドを読んで気になる文章や間違ったコードを見かけたら、気軽に Pull Request を出して頂けると嬉しいです。Pull Request の送り方については GitHub の README をご参照ください。
原著における間違いを見つけたら『Rails のドキュメントに貢献する』を参考にしながらぜひ Rails コミュニティに貢献してみてください 🛠💨✨
本ガイドの品質向上に向けて、皆さまのご協力が得られれば嬉しいです。
Railsガイド運営チーム (@RailsGuidesJP)
Railsガイドは下記の協賛企業から継続的な支援を受けています。支援・協賛にご興味あれば協賛プランからお問い合わせいただけると嬉しいです。