今朝、といってもこれを書いているのは12日の早朝なのですが.. Mojolicious 4.60 がリリースされ CPANにおいてのリリースオーサーがMarcus Ramberg氏 になっていてちょいと驚いている僕です。まーPOD見るとProject Founderのはいつも通りのSebastian Riedel氏なので特に内紛があったとかそういうのじゃないでしょうねw そこらの事情に詳しい人いましたら是非Advent Calendarを書いていただきたいです。
追記
miyagawaさんからこんなツイートを頂きまして... ようはリリースオーサーが変わることは特に目新しいことじゃない!とのことですね。
@yusukebe there were released made by one of core developers in the past, nothing new.
===
さて、MojoliciousのWebアプリに限らず そのプロジェクトのトップ=いわゆるホームディレクトリ へのパスを取得して ごにょごにょ したいという要望は結構あります。例えば、前日・前々日と
という記事が本Advent Calendarで投稿されたのですが、本文中のコード中にそれぞれ違うやり方でプロジェクト・ホームへのパスを探っています。前者はPath::Classを使った方法、もう後者はAmon2::Utilを模倣しFile::Specを内部で利用しています。こうしたやり方はMojo/Mojoliciousネームスペースに依存しないという意味ではよいかと思われます。が、ある程度自作しているので、もしカジュアルに使うとかMojo/Mojoliciousの機能をフルに使いこなしたい場合は Mojo::Home というその名もズバリなモジュールがMojoliciousディストリビューションの中に同封されMojolicious.pmなどで使われています。その挙動に興味があったのでソースコード見ながら使ってみました。
例えば、LiteでないMojoliciousアプリをつくってControllerの中で呼んでみましょう。プロジェクト・ホーム直下の log ディレクトリのへのパスを取得するには以下のコードでまかなえます。
package MyApp::Web::Example;
use Mojo::Base 'Mojolicious::Controller';
use Mojo::Home;
sub welcome {
my $self = shift;
my $home = Mojo::Home->new();
$home->detect( ref $self );
my $log_dir = $home->rel_dir('log');
$self->render( text => "project directory is '$log_dir'" );
}
1;
Mojo::Homeモジュールのインスタンスで detect
メソッドを一度発行するのですが、その際に呼び出し元のパッケージ名を ref
関数で取得して渡しているのがポイントですね。一度 detect
メソッドを実行したら rel_dir
などで相対パスをこの場合「log」と指定して log
ディレクトリへのパスを キチンと 取得しています。
ちなみにController以外の場所でも use Mojo::Home
してパス解決をさせることは可能です。
package MyApp::Logic::SomeThing;
use Mouse;
use Mojo::Home;
use Cwd qw/abs_path/;
sub project_dir {
my $self = shift;
my $home = Mojo::Home->new;
$home->detect( ref $self );
my $project_dir = $home->rel_dir('.');
return $project_dir;
}
__PACKAGE__->meta->make_immutable();
無駄にMouseを使っていますがw project_dir
メソッドを実行すると今回はプロジェクト・ホームへの絶対パスを文字列で得ることが出来ます。
ちなみに、と、いいますが… もっと早く言ってくれよ! って感じかも知れませんが、 Mojolicious.pm のメソッドに home
というのものがありそれを使うのが一番短く楽に書けるので、実際はそうしましょう。Controllerから呼び出す場合は
package MyApp::Web::Example;
use Mojo::Base 'Mojolicious::Controller';
sub welcome {
my $self = shift;
my $log_dir = $self->app->home->rel_dir('log');
$self->render( text => "log directory is '$log_dir'" );
}
1;
これだけでOK!
で、本来ならソースコード見たのでもう少しネタはありますが、内部実装の話になっちゃうのでこの程度にとどめておきます。まーControllerや MyApp::Web
からならば使う機会はありそうですよね!!