Padrino Frameworkの最新事情と今後について
Padrino Frameworkについては公式サイト・日本語版を参照。
Padrino 0.12.3が先日リリースされましたが、最新の機能情報などをあまりウェブ上で見かけることがないので、解説しようと思います。
この文章は、Padrino 0.12.3における変更を網羅的に解説するものではなく、0.12.3に限らず最近の目立った変更・機能追加に要点を絞って書き進めます。
詳しい情報は、Padrinoの公式ブログの各エントリと、そこにリンクされているPull Request・Issueなどを確認してください。
また、つい最近Padrinoコアメンバー三名がRubyroguesで色々話してくれたみたいです。
書き起こしもあるようなので、興味のある方は是非確認してみてください。
機能追加など
大きいと思う機能追加について書きます。主観です。
Params Protection (0.12.2)
キャプチャ・クエリーに対するフィルターの設定を可能にします。
以前までも、パスに指定された文字列に存在するキャプチャに対して、正規表現などによるフィルタリングは可能でしたが、より柔軟な設定ができるという意味でもこちらの使用を推奨します。
# GET /a?name=1234&email=namusyaka@gmail.com&body=hey
# #=> {"name"=>"1234", "email"=>"namusyaka@gmail.com"}
get :a, params: [:name, :email] do
params.inspect
end
# GET /b?name=1234&email=namusyaka@gmail.com&body=hey
# #=> {"name"=>"1234", "body"=>0}
# GET /b?name=1234&email=namusyaka@gmail.com&body=1234
# #=> {"name"=>"1234", "body"=>1234}
get :b, params: [:name, body: Integer] do
params.inspect
end
# GET /c?name=1234
# #=> {"name"=>"4321"}
get :c, params: [name: proc{|v| v.reverse } ] do
params.inspect
end
# GET /d?name=1234
# #=> {}
get :d, params: false do
params.inspect
end
# GET /e?name=1234&email=namusyaka@gmail.com&body=hey
# #=> {"name"=>"1234", "email"=>"namusyaka@gmail.com", "body"=>"hey"}
get :e, params: true do
params.inspect
end
# GET /f/foo
# #=> {"id"=>0}
# GET /f/1234
# #=> {"id"=>1234}
get :f, map: "/f/:id", params: {id: Integer} do
params.inspect
end
コントローラに対しても使えます。
Sample::App.controller :asset, params: [:name, :email] do
# GET /asset/a/?name=namusyaka&email=namusyaka@gmail.com&body=hello
# #=> {"name"=>"namusyaka", "email"=>"namusyaka@gmail.com"}
get :a do
params.inspect
end
# GET /asset/b/1234?name=namusyaka&email=namusyaka@gmail.com&body=hello
# #=> {"id"=>"1234"}
get :b, with: [:id], params: false do
params.inspect
end
# GET /asset/c/1234?name=namusyaka&email=namusyaka@gmail.com&body=hello
# #=> {"name"=>"namusyaka", "email"=>"namusyaka@gmail.com", "body"=>"hello", "id"=>"1234"}
get :c, with: [:id], params: true do
params.inspect
end
end
params
というクラスメソッドによるフィルタリングもできます。
# GET /g?name=namusyaka&foobar=1234
# #=> {"foobar"=>1234}
# GET /g?name=namusyaka&foobar=hello
# #=> {"foobar"=>0}
params foobar: Integer
get :g do
params.inspect
end
cache_object helper (0.12.1)
名前通り、オブジェクトをキャッシュします。
get "/" do
cache_object 'key' do
# code
end
end
Generator周り
Helperジェネレータ (not released yet)
ヘルパーファイルを個別に作成できるようにするというものです。
以前まではコントローラファイルと一緒に作成する以外に、作成する方法はありませんでした。
**ただしこれは0.12.3には含まれません。**次回のリリースから使えるようになります。
padrino g helper hogehoge
今後について
今後のPadrinoがどうなっていくのかということについてです。ここでいう「今後」とは、Padrino 1.0リリースまでの話です。
これはPadrino core teamが取り組むべきこととして挙げていることを網羅的に解説しているわけではありません。
それらの中から特に重要であると考えられるものと、個人的に取り組むべきだと考えているものについて挙げています。
もしもPadrinoにコントリビュートしようと考えてくださる方がいれば、参考にしていただければと思います。
スレッドセーフ対応
要するにJRubyやRubiniusなどでも問題なく使えるように強化していこうということだと思います。
例えば、PadrinoはSinatraの上に乗っかっていると言ってもコアのルーティングは外部ライブラリであるhttp_routerに依存しており、このライブラリはスレッドセーフではありません。
Padrino Admin
現状、Padrino Adminによって作られるレコード一覧ページなどは、ページネーション等の仕組みがなく、デフォルトでは全てのレコードを一ページに一気に書き出そうとします。
当然重たいわけで、そういったページネーション対応などをも含めて1.0に向けて大きくバージョンアップさせようという話です。
主に以下のような機能追加・実装を目指しています。
・ページネーション対応
・Backboneなどを使ったUI
・モバイル対応 (後回しで良い気がする)
・パスワードリマインダー
・フィルター・検索
これらの対応は、Padrinoが対応しているORM全てを考慮しなければならないために大変ですが、orm_adapterというプロジェクトもあるようで、そういったGemを使いながら上手く解決したいところです。
ちなみにorm_adapterにはPadrinoとはまた違った方針があるようで、使うのであればforkするなりして、Padrinoのためのorm_adapterを作成する必要がありそうです。
新しいルーターの開発
http_routerはコードの量も多く、多分頭が良い人が書いたんだろうと思えるくらいには面倒臭いことをやっていて、コードを追うのも大変です。
加えて既にメンテナンスされていないという事情も相俟って、ルーティング周りのデバッグはなかなかに骨が折れる作業でした。
Padrinoの高速なルーティングを実現するために有用であったことは間違いないのですが、もはや使い続けるメリットよりもデメリットの方が上回っているため、1.0までに新しいルーターに書き換えられる予定です。
一応新しいルーターのベースとなるGemを公開しています。
http_routerと比較して何が違うのかという点については以下の通りです。
- Sinatra 2.0から導入予定のMustermannというパターンマッチングライブラリを使用している。
- ベンチマークの結果によると、http_routerより高速。
- コード量が少ない。
Sinatraより速くできるんじゃないかなあと思っています。
原則的にはhttp_routerによって実装されているPadrinoのルーティングとの後方互換性を保証しています。
従って、「過去のルーティングで動いていたものが新しいルーターになった途端動かなくなった」、ということは起こるべきではありません。
もし起こったら教えてください。直します。
Ruby 1.9のサポート終了
新しいルーターを導入するにあたって、前述のMustermannがRuby 2.0でしか動かないために1.9サポートを終了させようという流れがあります。
といってもこれは未定で、例えばMustermannをRuby 1.9シンタックスに書き換えたブランチを用意したりしているので、
これをGemとしてリリースして(mustermann19?)、当分はそれと本家Gemを分けて使っていくことになる可能性もあります。どうしましょう。
mustermann19というgemをリリースしました。
本家のテストとPadrino Frameworkのテストを全てパスするくらいにはちゃんと動いてくれています。
このお陰で、Ruby 1.9でも新ルーターを使うことができるようになりました。やったぜ。
mustermann19と本家のものとを比較して明らかに劣っている点は、内部キャッシュが厳密に働かないということくらいでしょうか。
本家Mustermannはいくつかの部分において、Ruby2.0から追加されたObjectSpace::WeakMapを使ってキャッシュを実現しているのですが、mustermann19からはその機能を削除しています。
とはいえ、そこまで性能に差は出ないだろうと考えています。なぜならルート探索の多くの部分では、Mustermannが生成してくれるRegexpを直接操作・使用しているためです。
もしもおかしな点などあれば教えてください。Pull Requestも歓迎します。
リファクタリング
例えばpadrino-genのいくつかのジェネレータ、およびそれらをサポートするためのモジュールは、お世辞にも綺麗なコードとは言えないですし、コードの見通しも悪いです。
codeclimateを見れば一目瞭然ですが、修正すべき事柄だと思います。
ドキュメント・公式サイトの更新
方々からお叱りを受けること早一年ですが、1.0までに公式サイトのアップデートと、ドキュメントをアップデートする予定です。
padrino-docsやpadrino-framework内のドキュメントの更新などが主です。
この文章は後々加筆修正される可能性があります。