« Google Analyticsを導入してみた。 | メイン | CGI.pmを継承して漢字コードの変換をする必要性に疑問 »

run_modesを省略するCGI::Application::Plugin 2

CatalystやSledgeというrichなFrameworkの話題が多いですが、シンプルなCGI::Applicationもまだまだ弄りがいありますよ。と前置き。

以前、CGI::Applicationでpost_dispatchで書いたCGI::Application::Plugin::Dispatchはすでに仕事でもデモでも使ってますが、1つ弱点があります。それはAUTOLOADを使っているのでAUTOLOADが使えない事です。なのでCaropyでは使用できませんでした。

そこでid:tociyukiさんのCatalyst解体CGI::Application::Plugin::AutoRunmodeを参考に書き直してみた。

package CGI::Application::Plugin::AutoDispatch;

use strict;
use warnings;
use base qw(Exporter);
our $VERSION = '0.01';

sub import{
    my $caller = scalar(caller);
    $caller->add_callback('prerun', \&_prerun_autodispatch);
    goto &Exporter::import;
}

sub _prerun_autodispatch{
    my $self = shift;
    my $pkg = ref($self);

    my %post_actions;
    my %actions;
    
    no strict 'refs';
    foreach my $sym ( values  %{$pkg . '::'} ){
        if (*{$sym}{CODE}){
            my $name = *{$sym}{NAME};
            if($name =~ /^post_dispatch_([a-z0-9]+)$/){
                $post_actions{$1} = $name;
            }elsif($name =~ /^dispatch_([a-z0-9]+)$/){
                $actions{$1} = $name;
            }
        }
    }
    use strict 'refs';
    
    if(lc($self->query->request_method) eq 'post'){
    	%actions = (%actions,%post_actions);
    }
    %actions = (%actions,$self->run_modes);
    $self->run_modes(%actions);
}

1;


使い方は、

package MyApp;
use strict;
use base qw(CGI::Application);
use CGI::Application::Plugin::AutoDispatch;
sub setup{
    my $self = shift;
    $self->start_mode('foo');
}
sub dispatch_foo{
}
sub dispatch_bar{
}
1;

dispatch_[a-z0-9]+、またはpost_dispatch_[a-z0-9]+の形でメソッドを定義しておくと、run_modesを書かなくても、prerun

foo=>dispatch_foo,
bar=>dispatch_bar

を設定します。run_modesを書くとそちらが優先されます。

ちなみにCatalystの最新5.51ではDispatcherが大きく書き変わって上のような方法をとっていないようにみえる。Catalystはソースが難しい。