Mojoliciousを使ってオレオレFW化への道 〜CLI機能の追加〜


最近、自分の中で中規模(WEBとちょっとしたバッチ数本)サイトを作成する時に以前はPHPを使用していたんですが、本業でPerlを触りだしたというのとCPANの便利さに慣れてしまって今ではPerlで作ることが多くなりました。 スタートアップを早めるために個人的に使いやすいFWを使ってプロジェクトのひな形を作っています。

プロジェクトのひな形を作る前にどのFWを使おうか迷ったんですが、MVCベースで依存性の低いものが欲しかったのとちょうどMojolicious3.0のリリース記事を見かけたのでMojoliciousを使うことにしました。ちなみにMojoliciousを使うのは今回が初めてです。

今回はMojoliciousにCLI機能を追加してみます。

広告

まず、最終的にこんな感じで実行したいです。

./script/cli Hoge

Hogeはファイル単位に分割されたcli用モジュール名です。

Mojoliciousにcil機能を追加した結果、下記のようなファイル構成になりました。mojo generate app MyApp::WebとすることでWeb用のネームスペースを確保しています。

my_app/
├── lib
│   └── MyApp
│       ├── Cli
│       │   └── Hoge.pm
│       ├── Cli.pm
│       ├── Web
│       │   └── Example.pm
│       └── Web.pm
├── log
├── public
│   └── index.html
├── script
│   ├── cli
│   └── my_app
├── t
│   └── basic.t
└── templates
    ├── example
    │   └── welcome.html.ep
    └── layouts
        └── default.html.ep

新たに追加したファイルはこんな感じになっています。

追加したファイル

MyApp/Cli.pm

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
 
package MyApp::Cli;
use Mojo::Base 'Mojo::Command';
 
use FindBin;
use File::Basename 'dirname';
use File::Spec::Functions qw(catdir splitdir);
 
sub development_mode {
    my $self = shift;
}
 
sub production_mode {
    my $self = shift;
}
 
sub setup {
    my $self = shift;
    my $app  = $self->app;
    my $mode = $app->mode;
 
    # setup each mode
    eval {
        my $method = "${mode}_mode";
        $self->$method;
    };
}
 
1;

MyApp/Cli/Hoge.pm

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
 
package MyApp::Cli::Hoge;
use Mojo::Base 'MyApp::Cli';
 
sub run {
    my $self = shift;
    local @ARGV = @_; 
 
    $self->setup;
}
 
1;

script/cli

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
 
use UNIVERSAL::require;
use File::Basename 'dirname';
use File::Spec::Functions qw(catdir splitdir);
 
# Source directory has precedence
my @base = (splitdir(dirname(__FILE__)), '..');
my $lib = join('/', @base, 'lib');
-e catdir(@base, 't') ? unshift(@INC, $lib) : push(@INC, $lib);
 
my $cmd = shift @ARGV;
my $module = "MyApp::Cli::$cmd";
$module->require;
$module->run( @ARGV );

まとめ

とりあえず、./script/cli Hogeの形でモジュールを実行することが出来るようになりました。cli側で$app->pluginメソッドも使えるので、web側と同じようにconfigやdatabase、その他のpluginをロードして利用することが出来るようになっています。

database周りと入力値の検証用ライブラリ、ロジックの分離ができたら実際にアプリを作ってみたいと思います。

関連記事