make it so you can override the role metaclass just like the attribute metaclass...
Chris Prather [Wed, 15 Apr 2009 00:27:01 +0000 (20:27 -0400)]
lib/Moose/Meta/Class.pm
lib/Moose/Meta/Role.pm
lib/Moose/Role.pm
t/030_roles/038_role_metaclass.t [new file with mode: 0644]

index ceec428..5d93a16 100644 (file)
@@ -41,17 +41,24 @@ __PACKAGE__->meta->add_attribute('error_class' => (
     default  => 'Moose::Error::Default',
 ));
 
+__PACKAGE__->meta->add_attribute('role_metaclass' => (
+    accessor => 'role_metaclass',
+    default => 'Moose::Meta::Role',
+));
+
 
 sub initialize {
     my $class = shift;
     my $pkg   = shift;
-    return Class::MOP::get_metaclass_by_name($pkg) 
-        || $class->SUPER::initialize($pkg,
+    if (my $meta = Class::MOP::get_metaclass_by_name($pkg)) {
+        return $meta;
+    }
+    return $class->SUPER::initialize($pkg,
                 'attribute_metaclass' => 'Moose::Meta::Attribute',
                 'method_metaclass'    => 'Moose::Meta::Method',
                 'instance_metaclass'  => 'Moose::Meta::Instance',
                 @_
-            );    
+            );
 }
 
 sub create {
index 2ca0c91..0a38454 100644 (file)
@@ -119,6 +119,15 @@ foreach my $action (
 
 ## some things don't always fit, so they go here ...
 
+sub initialize {
+    my $class = shift;
+    my $pkg   = shift;
+    if (my $meta = Class::MOP::get_metaclass_by_name($pkg)) {
+        return $meta;
+    }
+    return $class->SUPER::initialize($pkg, @_);
+}
+
 sub add_attribute {
     my $self = shift;
     my $name = shift;
index e98b1b3..62defbb 100644 (file)
@@ -139,6 +139,19 @@ sub init_meta {
     my $meta;
     if ($role->can('meta')) {
         $meta = $role->meta();
+        # we might have had metaclass called on us
+
+        if (blessed($meta) && $meta->isa('Moose::Meta::Class')) {
+            $metaclass = $meta->{'role_metaclass'} || $metaclass;
+            Class::MOP::remove_metaclass_by_name($role);
+            $meta = $metaclass->initialize($role);
+            $meta->add_method(
+                'meta' => sub {
+                    # re-initialize so it inherits properly
+                    $metaclass->initialize( ref($_[0]) || $_[0] );
+                }
+            );
+        }
 
         unless ( blessed($meta) && $meta->isa('Moose::Meta::Role') ) {
             require Moose;
@@ -147,7 +160,6 @@ sub init_meta {
     }
     else {
         $meta = $metaclass->initialize($role);
-
         $meta->add_method(
             'meta' => sub {
                 # re-initialize so it inherits properly
diff --git a/t/030_roles/038_role_metaclass.t b/t/030_roles/038_role_metaclass.t
new file mode 100644 (file)
index 0000000..bb9c0c2
--- /dev/null
@@ -0,0 +1,34 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 1;
+use Moose ();
+
+BEGIN {
+
+    package My::Meta::Role;
+    use Moose;
+    extends 'Moose::Meta::Role';
+
+    has test_serial => (
+        is      => 'ro',
+        isa     => 'Int',
+        default => 1,
+    );
+    no Moose;
+
+}
+{
+
+    package MyRole;
+    use metaclass 'Moose::Meta::Class' =>
+        ( role_metaclass => 'My::Meta::Role' );
+    use Moose::Role;
+
+    no Moose::Role;
+};
+
+isa_ok( MyRole->meta, 'My::Meta::Role' );
+
+# my $role = MyRole->meta->create_anon_role;
+# is( $role->test_serial, 1, "default value for the serial attribute" );