6

ご挨拶、

I'm learning Moose and I'm trying to write a CGI::Application subclass with Moose, which is made difficult by the fact that CGI-App is not based on Moose.

In my other CGI-App subclasses, I like to have a parent class with a setup method that looks at the child class's symbol table and automatically sets up the runmodes. I figure I can use Moose's metaclass facilities to achieve the same thing in a cleaner way. So here is what I have in my parent class:

use MooseX::Declare;

class MyApp::CGI 
extends Moose::Object
extends CGI::Application { 

    method setup { 
        $self->start_mode( 'main' );

        my @methods = map { $_->name } $self->meta->get_all_methods;

        $self->run_modes( map  { /^rm_(.+)$/  => $_ }
                          grep { /^rm_/ }
                          @methods
                        );
    }

}

...and in my child class:

use MooseX::Declare;

class MyApp::CGI::Login 
extends MyApp::CGI { 
    method rm_main { 
        return "it works";
    }
}

I realized that the reason my runmodes were not getting setup properly is because setup is called by the CGI-App constructor, and Moose::Object is sticking its own constructor in my class. I tried to solve this with a method modifier:

around new { 
    $self = $orig->( @_ );
    $self->CGI::Application::new( @_ );
}

This gives me

Can't call method "BUILDARGS" on unblessed reference at ...Moose/Object.pm line 21.

しかし、私はこれを完全に間違った方法で行っていると感じています. Moose には、私がまだ発見していない、私が望むものを達成するためのはるかに優れた機能があります.

4

1 に答える 1

9

Moose::Cookbook::Basics::DateTime_ExtendingNonMooseParentMooseX::NonMooseはもう見ましたか?

更新:私は Moose やさまざまなテクニックにあまり詳しくありません。MooseX::Declareと を一緒に使用してモジュールをコンパイルすることができませんでしMooseX::NonMooseた。ただし、ここにうまくいくように見えるものがあります:

アプリケーション基本クラス

package My::App;

use Moose;
use MooseX::NonMoose;
extends 'CGI::Application';

sub setup {
    my $self = shift;
    $self->start_mode( 'main' );

    $self->run_modes(
        map { $_ = $_->name;
              /^rm_ (?<rm>.+) $/x ? ( $+{rm} => $_ ) : ()
        } $self->meta->get_all_methods
    );
}

"My::App"

派生クラス

package My::Login;
use Moose;
extends 'My::App';

sub rm_main { 'it works!' }

"My::Login"

脚本

#!/usr/bin/perl

use strict;
use warnings;

# For testing on the command line
use FindBin qw( $Bin );
use lib $Bin;

use My::Login;

my $app = My::Login->new;

$app->run;

出力

C:\Temp\f> t
Content-Type: text/html; charset=ISO-8859-1

it works!
于 2009-06-29T14:15:19.367 に答える