ROUTE 3390

備忘録的な用途で書いていますが、どなたかの役に立つ事があれば嬉しいです。

CGI::Application::DispatchとMouse(Moose)を使った時にハマったこと

CGI::Application::Dispatchで下記のようにargs_to_newを使うと、
実行するモジュールへの引数が指定出来る。

index.cgi

#!/usr/bin/perl

use strict;
use warnings;

use CGI::Application::Dispatch;

CGI::Application::Dispatch->dispatch(
    prefix  => 'Sasakure',
    table   => [
        ''    => { app => 'Blog', rm => 'posts' },
    ],
    args_to_new => {
        PARAMS => {
            foo => 'bar'
        },
    }
);

exit;

Sasakure/Blog.pm

package Sasakure::Blog;

use strict;
use warnings;

use base 'CGI::Application';

sub posts {
    $self = shift;
    warn $self->PARAMS->{foo};   # エラーログに「bar」が吐かれる。
}

1;

よーし!ディスパッチはできたから、最近かじっているMouseを利用してみよう!
という時に思わぬ事件。。

下記のように書いたらindex.cgiからパラメータが受け取れなくなってしまった。
Sasakure/Blog.pm

package Sasakure::Blog;

use base 'CGI::Application';

use Mouse;

__PACKAGE__->meta->make_immutable;
no Mouse;

sub posts {
    $self = shift;
    warn $self->PARAMS->{foo};   # そんなんねーよとエラー
}

1;


原因はnewにあった。
MooseやMouseで__PACKAGE__->meta->make_immutable;をすると、newというコンストラクタは呼ばれなくなる。
代わりにBUILDという名前のメソッドがその役割を担ようになる。


CGI::Application::Dispatchでは,コールするモジュールのnewメソッドとmode_paramメソッドを実行しようとする。

んで、そのときにargs_to_newで渡されたパラメータを受け取る。
それを1行で済ませるのが、use base qw/CGI::Application/;だ。
継承することで、newメソッドとか書く必要がなくなる。


でも何度も言うようにMouseでmake_immutableすると、、newが呼ばれなくなる。
というわけで下記のように書くことで、無事index.cgiからパラメータを受け取れるようになった。

Sasakure/Blog.pm

package Sasakure::Blog;

#use base 'CGI::Application';

use Mouse;

# index.cgiからのパラメータをしまう場所を用意
has 'params' => (
    is       => 'rw',
    isa      => 'ArrayRef[Str]',
);

__PACKAGE__->meta->make_immutable;
no Mouse;

sub BUILD { # newに代わるメソッドでパラメータを受け取る
    my $self = shift;
    my ( $dispatch_args, ) = @_;
    $self->{params} = $dispatch_args->{PARAMS};
}

sub mode_param { # これ使わなくても用意しとかないとDispatchがエラー出しよる
    my $self = shift;
    return $self;
}

sub posts {
    $self = shift;
    warn $self->params->foo;   # 無事、エラーログに「bar」が吐かれる。
}

1;