Dealing with multiple-inherited constructors in Moose

cgiapp, moose, mop, oop, perl

Solution

Have you already looked at Moose::Cookbook::Basics::DateTime_ExtendingNonMooseParent and MooseX::NonMoose?

Update: I am not very familiar with Moose and assorted techniques. I was not able to get the modules to compile using `MooseX::Declare` and `MooseX::NonMoose` together. However, here is something that seems to work:

Application Base Class

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"

Derived Class

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

sub rm_main { 'it works!' }

"My::Login"

Script

#!/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;

Output

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

it works!

Problem

Greetings, 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. ``` I have a feeling, however, that I'm going about this in completely the wrong way, and Moose has a much better facility for achieving what I want, which I have not as yet discovered.

Original source