fix init_meta order when multiple also package are specified
Jesse Luehrs [Mon, 30 Apr 2012 20:52:59 +0000 (15:52 -0500)]
Changes
lib/Moose/Exporter.pm
t/metaclasses/moose_exporter.t

diff --git a/Changes b/Changes
index 8aa9b25..d7abe16 100644 (file)
--- a/Changes
+++ b/Changes
@@ -3,6 +3,12 @@ for, noteworthy changes.
 
 {{$NEXT}}
 
+  [BUG FIXES]
+
+  * Fix init_meta order when multiple also packages are specified (this matters
+    when one of them is being used to actually initalize the metaclass,
+    typically with also => 'Moose'). Reported by Randy Stauner. (doy)
+
 2.0600 Sun, Apr 29, 2012
 
   [OTHER]
index b07a474..b32f302 100644 (file)
@@ -170,7 +170,7 @@ sub _make_exporter {
             $seen->{$package} = 1;
         }
 
-        return @also, map { _follow_also_real($_) } @also;
+        return map { $_, _follow_also_real($_) } @also;
     }
 }
 
index bed631b..fd0d9ea 100644 (file)
@@ -5,6 +5,7 @@ use warnings;
 
 use Test::More;
 use Test::Fatal;
+use Test::Moose;
 
 use Test::Requires {
     'Test::Output' => '0.01', # skip all if not installed
@@ -587,4 +588,94 @@ use Test::Requires {
     BEGIN { is_deeply(\@init_metas_called, [ 4, 3, 2, 1 ]) || diag(Dumper(\@init_metas_called)) }
 }
 
+# Using "also => [ 'MooseX::UsesAlsoMoose', 'MooseX::SomethingElse' ]" should
+# continue to work. The init_meta order needs to be MooseX::CurrentExporter,
+# MooseX::UsesAlsoMoose, Moose, MooseX::SomethingElse. This is a pretty ugly
+# and messed up use case, but necessary until we come up with a better way to
+# do it.
+
+{
+    my @init_metas_called;
+
+    BEGIN {
+        package AlsoTest::Role1;
+        use Moose::Role;
+
+        $INC{'AlsoTest/Role1.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package AlsoTest1;
+        use Moose::Exporter;
+
+        Moose::Exporter->setup_import_methods(
+            also => [ 'Moose' ],
+        );
+
+        sub init_meta {
+            shift;
+            my %opts = @_;
+            ::ok(!Class::MOP::class_of($opts{for_class}));
+            push @init_metas_called, 1;
+        }
+
+        $INC{'AlsoTest1.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package AlsoTest2;
+        use Moose::Exporter;
+        use Moose::Util::MetaRole ();
+
+        Moose::Exporter->setup_import_methods;
+
+        sub init_meta {
+            shift;
+            my %opts = @_;
+            ::ok(Class::MOP::class_of($opts{for_class}));
+            Moose::Util::MetaRole::apply_metaroles(
+                for => $opts{for_class},
+                class_metaroles => {
+                    class => ['AlsoTest::Role1'],
+                },
+            );
+            push @init_metas_called, 2;
+        }
+
+        $INC{'AlsoTest2.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package AlsoTest3;
+        use Moose::Exporter;
+
+        Moose::Exporter->setup_import_methods(
+            also => [ 'AlsoTest1', 'AlsoTest2' ],
+        );
+
+        sub init_meta {
+            shift;
+            my %opts = @_;
+            ::ok(!Class::MOP::class_of($opts{for_class}));
+            push @init_metas_called, 3;
+        }
+
+        $INC{'AlsoTest3.pm'} = __FILE__;
+    }
+
+    BEGIN { @init_metas_called = () }
+    {
+        package UsesAlsoTest3;
+        use AlsoTest3;
+    }
+    use Data::Dumper;
+    BEGIN {
+        is_deeply(\@init_metas_called, [ 3, 1, 2 ])
+            || diag(Dumper(\@init_metas_called));
+        isa_ok(Class::MOP::class_of('UsesAlsoTest3'), 'Moose::Meta::Class');
+        does_ok(Class::MOP::class_of('UsesAlsoTest3'), 'AlsoTest::Role1');
+    }
+
+}
+
 done_testing;