Sinatraのトップレベルスタイルで書かれたWebサーバーが,どのように起動するのかを解説します.
トップレベルスタイル とは、以下のような書き方のことを指します:
require 'sinatra' get '/hello' do 'hogehoge' end
このスタイルで書かれたSinatraのWebサーバーには,サーバーを起動するような記述が一切ありません.どのようにWebサーバーが起動しているのでしょうか?
TL;DR
以下のようなトップレベルスタイルのSinatraアプリケーションは、
require 'sinatra' get '/' do 'hoge' end
以下のようなコードと概ね等価ということです:
# 空のモジュラーアプリの定義 require 'sinatra/base' class Application < Sinatra::Base end # DSLの定義 [:get, :post, :put, :delete].each do |method_name| define_method method_name do |*args, &blk| Application.send(method_name, *args, &blk) end end # Webサーバー起動処理の登録 at_exit { Application.run! } # アプリケーションの定義 get '/' do 'hoge' end
解説
モジュラースタイル
Sinatraでは、上記のようなトップレベルスタイルを用いる以外にも、 モジュラースタイル を用いる方法があります。
モジュラースタイルというのは、以下のような書き方を指します:
require 'sinatra/base' class MySinatraApplication < Sinatra::Base get '/hello' do 'hogehoge' end end MySinatraApplication.run!
この用に定義されたWebアプリケーションのことを モジュラーアプリ と呼びます。
空のモジュラーアプリの定義
require 'sinatra'
と書くと、 Sinatra::Application
という名前の空のモジュラーアプリが定義されます。
DSLの定義
また、require 'sinatra'
が実行されることで、 Sinatra::Delegator
というモジュールがグローバルに extend
され、get
とか post
などの、SinatraのDSLで使われるメソッドが定義されます。
これらのメソッドは Sinatra::Application.get
や Sinatra::Application.post
に”リダイレクト”されます。
つまり、以下のコードは、
require 'sinatra' get '/' do 'hoge' end
以下のコードと等価です:
require 'sinatra' Sinatra::Application.get '/' do 'hoge' end
詳しい実装が気になる人は sinatra/base.rb at master · sinatra/sinatra · GitHub を読んで下さい。 メタプログラミングのお手本のような使い方だと思います。
サーバーの起動
Rubyには Kernel.#at_exit
というメソッドがあります。
このメソッドにブロックを与えると、インタプリタ終了時にそのブロックが実行されます。
Application::Sinatra
の定義の中で at_exit
が呼び出されている部分があり、Webサーバーの起動処理が登録されています。
これによって、スクリプトの実行終了時にWebサーバーが起動します。
まとめ
つまり、以下のようなトップレベルスタイルのSinatraアプリケーションは、
require 'sinatra' get '/' do 'hoge' end
以下のようなコードと概ね等価ということです:
# 空のモジュラーアプリの定義 require 'sinatra/base' class Application < Sinatra::Base end # DSLの定義 [:get, :post, :put, :delete].each do |method_name| define_method method_name do |*args, &blk| Application.send(method_name, *args, &blk) end end # Webサーバー起動処理の登録 at_exit { Application.run! } # アプリケーションの定義 get '/' do 'hoge' end