Problem with mixins in a MooseX::NonMoose class

390 views Asked by At

Consider the following:

package MyApp::CGI;

use Moose;
use MooseX::NonMoose;
use Data::Dumper;

extends 'CGI::Application';

BEGIN { 
    print "begin isa = " . Dumper \@MyApp::CGI::ISA;
};

print "runtime isa = " . Dumper \@MyApp::CGI::ISA;

... 

The output when this compiles is:

begin isa = $VAR1 = [
          'Moose::Object'
        ];
runtime isa = $VAR1 = [
          'CGI::Application',
          'Moose::Object'
        ];

Why do I care? Because when I try to use a CGI::Application::Plugin::* class, it expects me to be inheriting from CGI::Application at compile-time already. The plugin class tries to call add_callback as a class method on my class, but can't, because my @ISA isn't set up yet.

What's the best way to solve this? Would tweaking @ISA manually in a BEGIN block interfere with MooseX::NonMoose?

Edit

The following appears to work, but I find it offensive:

package MyApp::CGI;

use Moose;
use MooseX::NonMoose;

use base 'CGI::Application';
extends 'CGI::Application';

I don't know enough (or anything, really) about Moose internals to know if this is a good idea.

1

There are 1 answers

2
Ether On BEST ANSWER

I don't find use base 'CGI::Application'; extends 'CGI::Application'; to be terribly ghastly because it does precisely what you need:

  • At compile-time, @ISA contains 'CGI::Application', which exactly satisfies the usage requirements of CGI::Application::Plugin::*
  • At runtime, your class is a Moose descendant of CGI::Application, with all the ensuing benefits (being able to design the composition of your class with Moosey meta goodness). It's only after the extends 'CGI::Application' line is encountered that any work is done (i.e methods are called on your class) that rely on the work done by the extends statement: that your class descends from Moose::Object and you have a meta-class installed.

That said, jrockway's solution should also work:

BEGIN { extends 'CGI::Application' }

...where you get all the Moosey meta goodness just a little ahead of schedule from when you need it, and it shouldn't be too ahead of schedule, provided you already called use Moose and use MooseX::NonMoose in order to define extends.

(Addendum: Now I'm pondering the complilational complexities of creating the ability to force the parsing of a keyword at compile-time that are parsed immediately such as if they were wrapped in a BEGIN block. e.g. something like if Moose.pm declared use compiletime qw(extends). It would be a nice piece of syntactic sugar for sure.)