MT アプリケーションを Sinatra like に記述できる MT::App::Lite 作った
Movable Type には、MT::App という Web アプリケーションを記述するための基底クラスがありますが、結構慣れが必要なのと癖があることもあって、もっと手軽に Sinatra like にアプリケーションを記述できる、フレームワーク的なものが欲しいなーと常々思っていました。
とりあえずいろいろやりたいことは残っていますが、動くところまでできたので、紹介します。
現状では、PSGI でのみ動作します。
概要
以下のような感じでMTアプリケーションを記述します。
package MyLiteApp; use strict; use MT::App::Lite; setup Renderer => 'Xslate'; get '/' => sub { my $app = shift; $app->render('index.tt', { blog => MT->model('blog')->load(1), entries => [MT->model('entry')->load({blog_id => 1})], }); }; get '/entry/:id' => sub { my $app = shift; $app->render('entry.tt', { blog => MT->model('blog')->load(1), entry => [MT->model('entry')->load($app->param('id'))], }); }; 1; __DATA__ @@ index.tt <!doctype html> <html> <head> <meta charset="utf-8"> <title><: $blog.name :></title> </head> <body> <ul> : for $entries -> $entry { <li><a href="<: $entry.permalink :>"><: $entry.title :></a></li> : } </ul> </body> </html> @@ entry.tt <!doctype html> <html> <head> <meta charset="utf-8"> <title><: $entry.title :> | <: $blog.name :></title> </head> <body> <h1><: $entry.title :></h1> <div> <: $entry.text | mark_raw :> </div> </body> </html>
1ファイル完結型です。(正確にはプラグインの config.yaml が必要)
多分、フォームとか作るのに便利だと思います。
仕様
MT アプリケーションのハンドラ内で、Router::Simple::Sinatraish でエクスポートされる、get や post などの関数を使って、ルートを記述します。
そのファイル中の __END__ セクションに、テンプレートを書きます。
__END__ セクションに記述したテンプレートは、Data::Section::Simple によって、MT::App::Lite に渡されます。
テンプレートは、Text::Xslate を標準のテンプレートエンジンにしています。申し訳程度に MTML 用のテンプレートエンジンも用意しましたが、ここでわざわざ使う必要はない気がします。
MT::App::Lite::Renderer::Foo という形で、render メソッドと render_string メソッドを用意すれば、任意のテンプレートエンジンを利用することは可能です。
また、MT::App::Lite を use すると、自動的に MT::App を継承することになるので、MT::App っぽい書き方もできるのかもしれません。
基本的には、MT::App に Web アプリケーションを記述するための機能はひと通り揃っているので、便利っぽいモジュールを糊付けしたような実装です。
MT アプリケーションのプラグインを作成する
このモジュールを使った、MTアプリケーションのプラグインの作り方です。
最小限の config.yaml と、ハンドラを用意します。
config.yaml
name: MyLiteApp id: myliteapp applications: lite_app: handler: MyLiteApp script: sub { 'app' } cgi_path: sub { '/' }
MyLiteApp (handler)
package MyLiteApp; use strict; use MT::App::Lite; setup Renderer => 'Xslate'; get '/' => sub { my $app = shift; $app->render('index.tt', { blog => MT->model('blog')->load(1), entries => [MT->model('entry')->load({blog_id => 1})], }); }; get '/entry/:id' => sub { my $app = shift; $app->render('entry.tt', { blog => MT->model('blog')->load(1), entry => [MT->model('entry')->load($app->param('id'))], }); }; 1; __DATA__ @@ index.tt <!doctype html> <html> <head> <meta charset="utf-8"> <title><: $blog.name :></title> </head> <body> <ul> : for $entries -> $entry { <li><a href="<: $entry.permalink :>"><: $entry.title :></a></li> : } </ul> </body> </html> @@ entry.tt <!doctype html> <html> <head> <meta charset="utf-8"> <title><: $entry.title :> | <: $blog.name :></title> </head> <body> <h1><: $entry.title :></h1> <div> <: $entry.text | mark_raw :> </div> </body> </html>
これで、http://yourdomain/app/ や、http://yourdomain/app/entry/:id にアクセスするとテンプレートの内容が描画されます。
まとめ
本当は、Movable Type Advent Calendar 2013 の自分担当日のネタとして作ろうと考えていたんですけど、実装する暇がなく、今日に至ります。
便利な気がするので、メンテしていこうと思います。まだいろいろと実装したいことや、実装すべきことがあります。
現時点ではちょっとした Viewer やフォームを作るのには便利な気がしています。