はじめに
SinatraはRubyで記述されたWebアプリケーションを素早く,簡単につくるためのDSL(ドメイン固有言語)です。
すでに第7回で,原悠さんにより「小規模Webアプリのためのフレームワーク,Sinatra」というかたちで紹介されています。
簡潔な文法で,高い表現力を持つSinatraは,アメリカのRubyコミュニティや企業を中心に,瞬く間にユーザを増やしました。また,Rubyという一言語に留まらず(※1),Sinatraを模したフレームワークが多く作られている現状からも,SinatraはWebアプリケーション開発そのものにも大きな影響を与えたと言えます。
最近ではここ日本でも,個人利用を中心に,そこかしこでSinatraを使って開発をしている,という話を聞くようになりました。筆者自身,1ユーザとして現在業務で利用しており,1年前は知る人ぞ知る存在だったSinatraは,実際に商用でも使われるという段階にきています。こうして気運が高まる中,2010年3月23日,ついにSinatra初のメジャーバージョンである1.0がリリースされました。
今回は,この1.0リリースを踏まえ,公式ドキュメントをもとに,改めてSinatraの世界を概観していきます。また,本連載ではSinatraの基本的な使い方に関しては触れません。有志による,公式のREADMEの素晴らしい翻訳があります。そちらを一読することをおすすめし,それに代えさせていただきます。
- ※1
- ScalaのStep,PHPのlimonade,PerlのSchenker,PythonのJuno,JavaScriptのExpressなど
Sinatra1.0
それでは,公式のFAQをもとにSinatra1.0のツアーをしていきましょう。
方向性
初のメジャーバージョンとなると,Railsのように目玉機能を期待してしまいますが,Sinatra1.0においては,見かけ上そこまでの大幅な変更はありません。新機能の追加というよりは,0.9xまでの大半のコードベースの動作を保証しつつ,これまで右往左往していた内部構造をきっちりと固める,という方向性のようです。
旧バージョンとの互換性
Sinatra1.0において,最も大きな変更は,0.3以降の互換性を維持するためにサポートされていた,非推奨機能の後方互換性を捨てるということです。これは先に述べた,内部構造を固めるという方針の反映でもあるでしょう。
それまでの安定バージョンである0.9.6までの0.9x系には,互換性保証のためのcompat.rbというライブラリが同梱され,非推奨機能の使用時に,"deprecated"(廃止予定)であるという旨のワーニングメッセージが通知されていました。1.0においては,ついにこれらの機能のサポートが明確に打ち切られるということになります。
ほとんどの機能には対応機能が存在しますが,ないものもありますので,移行の際には注意が必要です。
表1 Sinatra1.0で廃止となる機能と,推奨される方法・機能の対応表
| 廃止となる非推奨機能 | 今後推奨される対応方法・機能 |
|---|---|
| sinatra/testライブラリと,それに関連するモジュール,クラス,API | Rack::Testの利用 |
| sinatra/test/spec, sinatra/test/bacon, sinatra/test/rspec等のライブラリ | 使用しない |
| Sinatra::Defaultクラス | Sinatra::Baseクラス(統合された) |
| :views_directoryオプション | :viewsオプション |
| erb,buider,haml,sass等のテンプレート表示用ライブラリの自動ロード | 明示的なライブラリのロード |
| media_typeメソッド | mime_typeメソッド |
| mimeメソッド | mime_typeメソッド |
| send_dataメソッド | 使用しない |
| Sinatra::Event,Sinatra::EventContextクラス | 現状のextensionsAPIの利用 |
| set_option,set_optionsメソッド | setメソッド |
| :envオプション | :environmentオプション |
| stopメソッド | haltメソッド |
| entity_tagメソッド | etagメソッド |
| headersメソッド | response['Header-Name']への代入 |
| Sinatra.application | Sinatra::Application |
| Sinatra.application=nilによるアプリケーションのリセット | 明示的なリセットは必要なし |
| Sinatra.defautl_optionsによるデフォルト設定 | Sinatra::Base.set(:key:value)での設定 |
| Sinatra::ServerError | すべて内部エラーとして扱われ,HTTPステータスコード500のエラーとして処理 |
中でも,移行時に直ぐに影響が出そうなのは,テンプレート表示用ライブラリを明示的にrequireする必要がある,という点でしょうか。
また,Sinatra::Defaultクラスが無くなり,Sinatra::Baseクラスと統合するのも,拡張モジュールの作者にとっては影響がある可能性があります。これについては「拡張モジュールの作成」で後述します。
新しい機能
追加機能に関しては,CHANGESドキュメントを参照すると概観できます。以下,順に見ていきましょう。
- afterメソッド。beforeメソッドに対して,共通の後処理も可能に。
- Tiltの採用。Tiltはテンプレートエンジンのインタフェースを統合するための抽象レイヤで,キャッシュ等の機能も提供される。また,それに伴いmustacheやliquidほか,新たなテンプレートエンジンもサポートに。
- ERB,Erubis,Hamlなどのコンパイルを初回起動時に行うことによる,パフォーマンス最適化。
- settingsメソッド。setで設定した値を,classとrequest両方のスコープから参照できる。optionsのより良い代替手段となる。
- オプション:reload_templates。trueにした場合,コンパイル済みのテンプレートのキャッシュが行われない。
- erubisヘルパメソッド。Erubisをテンプレートエンジンとして選択可能になる。
- cache_control,expiresメソッド。Cache-ControlヘッダによるHTTPキャッシュの制御が可能になった。
- 起動時の-oオプション。アドレスを指定して起動出来るようになった。
- Rack::Session::Cookieクラス。テスト実行環境において利用できる。
- 拡張モジュールによって基底クラスに変更が加えられた場合も,Sinatra::Baseのサブクラス生成時に,動的にルーティングやbeforeフィルタ,テンプレート,エラー処理が解決されるようになった。
- オプション:raise_errorsの動作の変更。trueの場合,以前までエラーはアプリケーションの外側でraiseされていたが,基底クラス内でraiseされるようになった。falseの場合は,errorブロックがあれば処理され,ステータスコード500のエラーとして処理される。
- passメソッドを使用して,かつルーティングにマッチしない場合,または全てのルーティングがpassされた場合,X-Cascadeヘッダが付加されるようになった。
- 静的ファイルを返す場合はフィルタ処理が機能しないようになった。
- passメソッドの引数にブロックが渡せるようになった。passした後,その次のルーティングがマッチしない場合に実行される。
afterメソッドは初期のバーションから永らく姿を消しており,筆者の個人的には待望していたメソッドですが,やっと使えるようになりました。
目立たない変更ですが,起動時の-oオプションの追加により複数のSinatraアプリケーションが80番ポートで起動できるようになったことも,大変便利でしょう。
テンプレートに関する改善点も多いです。起動時にコンパイルされ,キャッシュもされることで,大幅にパフォーマンスが上がりました。しかし,これがデフォルトの動作になるため,キャッシュされたくないビューに関しては追加されたオプション:reload_templatesをtrueにする必要があり,注意する必要があります。
総評すると,派手さはありませんが,細かいところまで配慮が行き届き,商用利用をみこした改善が重ねられた,と言えるのではないでしょうか。

