え〜 この記事を書いている今から数えて「昨日」 ボケて に関わるメンバーで忘年会がありまして、当初はほそぼそとやっていたサービスが、例えばiOSとAndroidアプリのダウンロード数の合計が「250万」となり、大きなインパクトを持ちだしたわけで、感慨深いものがあると感じました。
さてそんなことも加味して、そのアプリにもWeb APIを提供している「バックエンド」で使っているとあるモジュールの話をします。それが Bokete.pm です。Mojoliciousで動いている部分が現状は大半なので、大抵は
$ mojo generate app Bokete::Web
のように作成され、ネームスペースをこの場合 Web層 と分けているという前提で話を進めます。とすると、トップレベルである Bokete.pm には特に書くこともあまり無いように見受けられますが、ボケてのアプリでは設定のロード周りを記述しています。
猫で著名なあずまさんが Configプラグインで使う実用的な外部設定ファイルの一例 という記事を投稿していましたが、僕の場合はなるべくWeb層以外でMojo/Mojoliciousのモジュールに依存させたくないという方針というかコダワリがありまして自分で設定のローダーを書いています。
といってもtokuhirom氏のWAF Amon2 の昔のローダーを軽く、いや、かなりパクってます。今では Amon2::Util の部分ですね。僕がローダーで考慮して結果的にどのようになったかというと…
- 設定ファイルはPerlスクリプト
- 設定ファイルを含めプロジェクトのルート・ディレクトリへのパス解決をする
- 環境変数「PLACK_ENV」を見て開発環境と本番を分ける
- また環境変数「BOKETE_CONFIG」に値があるとそれを設定ファイルとみなす
- ごにょれば テスト時にTest::mysqldのconnect_infoなどをある意味動的に渡すことが出来る
- 脱線しますがHarrietとか使うとテスト時は更に便利!
って具合です。ではその Bokete.pm をそのまま貼り付けちゃいます!ボケてのコードをそのまま晒すのはコレが初めて!!
package Bokete;
use strict;
use warnings;
use File::Spec;
use Carp qw/croak/;
our $VERSION = '0.40'; # Delta
sub config {
my $filename = Bokete->config_file();
my $config = do $filename;
croak ("Cannnot load configuration file: $filename") if $@;
return $config;
}
sub config_file {
my $filename = $ENV{BOKETE_CONFIG};
if( !$filename ) {
my $mode = $ENV{PLACK_ENV} || 'development';
$filename = File::Spec->catfile( Bokete->base_dir(), 'config', $mode . '.pl' );
}
$filename = readlink $filename || $filename;
croak("Cannot find configuration file: $filename") unless -f $filename;
return $filename;
}
sub base_dir {
my $path = ref $_[0] || $_[0];
$path =~ s!::!/!g;
if ( my $libpath = $INC{"$path.pm"} ) {
$libpath =~ s!(?:blib/)?lib/+$path\.pm$!!;
return File::Spec->rel2abs( $libpath || './' );
}
return File::Spec->rel2abs( './' );
}
1;
こうすることで、アプリケーションのどこからでも設定情報を Bokete->config()
で呼び出すことが出来ますね。また上記した通りテスト時にもテンポラリーに立ち上げたMySQLやmemcachedの接続情報を設定ファイルとしてアプリ側に渡して、当然ながら同じインターフェースで取り扱いが出来ます。便利〜
以上。実際にプロダクトで使われている Bokete.pm の紹介でした。