Fixed non-moose classes initialization order issues. Not quite as fugly as I first...
Tomas Doran [Tue, 21 Apr 2009 00:27:57 +0000 (00:27 +0000)]
Changes
lib/Catalyst.pm
t/unit_metaclass_compat_non_moose_controller.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 8581c86..2e5489c 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
 # This file documents the revision history for Perl extension Catalyst.
 
+        - Work around issues in Moose with initialization order of multiple
+          levels of non-Moose classes inheriting from a Moose class (t0m)
+          - Test for this
         - Add backwards compatibility method for Catalyst::Log->body, which
           has been made private (t0m)
         - Fix so that calling $c->req->parameters(undef) does not flatten
index 664f0d2..52b7787 100644 (file)
@@ -2,6 +2,7 @@ package Catalyst;
 
 use Moose;
 extends 'Catalyst::Component';
+use Moose::Util qw/find_meta/;
 use bytes;
 use Scope::Upper ();
 use Catalyst::Exception;
@@ -2161,6 +2162,14 @@ sub setup_components {
 
 =cut
 
+sub _controller_init_base_classes {
+    my ($class, $component) = @_;
+    foreach my $class ( reverse @{ mro::get_linear_isa($component) } ) {
+        Moose->init_meta( for_class => $class )
+            unless find_meta($class);
+    }
+}
+
 sub setup_component {
     my( $class, $component ) = @_;
 
@@ -2168,6 +2177,14 @@ sub setup_component {
         return $component;
     }
 
+    # FIXME - Ugly, ugly hack to ensure the we force initialize non-moose base classes
+    #         nearest to Catalyst::Controller first, no matter what order stuff happens
+    #         to be loaded. There are TODO tests in Moose for this, see
+    #         f2391d17574eff81d911b97be15ea51080500003
+    if ($component->isa('Catalyst::Controller')) {
+        $class->_controller_init_base_classes($component);
+    }
+    
     my $suffix = Catalyst::Utils::class2classsuffix( $component );
     my $config = $class->config->{ $suffix } || {};
 
diff --git a/t/unit_metaclass_compat_non_moose_controller.t b/t/unit_metaclass_compat_non_moose_controller.t
new file mode 100644 (file)
index 0000000..d2a61d9
--- /dev/null
@@ -0,0 +1,26 @@
+use Catalyst ();
+
+{
+    package TestApp::Controller::Base;
+    use base qw/Catalyst::Controller/;
+}
+{
+    package TestApp::Controller::Other;
+    use base qw/TestApp::Controller::Base/;
+}
+
+Catalyst->setup_component('TestApp::Controller::Other');
+Catalyst->setup_component('TestApp::Controller::Base');
+
+use Test::More tests => 1;
+use Test::Exception;
+
+# Metaclass init order causes fail.
+# There are TODO tests in Moose for this, see
+# f2391d17574eff81d911b97be15ea51080500003
+# after which the evil kludge in core can die in a fire.
+
+lives_ok {
+    TestApp::Controller::Base->get_action_methods
+} 'Base class->get_action_methods ok when sub class initialized first';
+