Allow code refs to act on foreign classes for delegator generation
Yuval Kogman [Sun, 30 Apr 2006 12:46:01 +0000 (12:46 +0000)]
lib/Moose/Meta/Class.pm
t/070_delegation.t

index f5d211a..f7a2252 100644 (file)
@@ -142,6 +142,8 @@ sub generate_delegation_list {
     if ( reftype($delegation) eq "CODE" ) {
         return $delegation->( $self, $delegator_meta );
     } elsif ( blessed($delegation) eq "Regexp" ) {
+        confess "For regular expression support the delegator class/role must use a Class::MOP::Class metaclass"
+            unless $delegator_meta->isa( "Class::MOP::Class" );
         return grep { $_->{name} =~ /$delegation/ } $delegator_meta->compute_all_applicable_methods();
     } else {
         confess "The 'handles' specification '$delegation' is not supported";
@@ -156,20 +158,18 @@ sub _guess_attr_class_or_role {
     confess "Generative delegations must explicitly specify a class or a role for the attribute's type"
         unless $isa || $does;
 
-    # if it's a class/role name make it into a meta object
-    for (grep { defined && !ref($_) } $isa, $does) {
-        confess "Generative delegations must refer to Moose class/role types"
-            unless $_->can("meta");
-        $_ = $_->meta;
-    }
-
     for (grep { blessed($_) } $isa, $does) {
         confess "You must use classes/roles, not type constraints to use delegation"
             unless $_->isa( "Moose::Meta::Class" );
     }
     
     confess "Cannot have an isa option and a does option if the isa does not do the does"
-        if $isa && $does and !confess->does( $does );
+        if $isa and $does and $isa->can("does") and !$isa->does( $does );
+
+    # if it's a class/role name make it into a meta object
+    for ($isa, $does) {
+        $_ = $_->meta if defined and !ref and $_->can("meta");
+    }
 
     return $isa || $does;
 }
index ab31491..be15852 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 34;
+use Test::More tests => 36;
 use Test::Exception;
 
 {
@@ -135,9 +135,23 @@ use Test::Exception;
             isa     => "ChildF",
             is      => "ro",
             default => sub { ChildF->new },
-            handles => sub { },
+            handles => qr/.*/,
         );
-    } "but not generative one";
+    } "can't use regexes on foreign classes";
+
+    my $delegate_class;
+    ::lives_ok {
+        has child_f => (
+            isa     => "ChildF",
+            is      => "ro",
+            default => sub { ChildF->new },
+            handles => sub {
+                $delegate_class = $_[1];
+            },
+        );
+    } "subrefs on non moose class give no meta";
+
+    ::is( $delegate_class, "ChildF", "plain classes are handed down to subs" );
 
     sub parent_method { "p" }
 }
@@ -146,13 +160,12 @@ use Test::Exception;
 
 isa_ok( my $p = Parent->new, "Parent" );
 isa_ok( $p->child_a, "ChildA" );
-#isa_ok( $p->child_b, "ChildB" ); # no accessor
+ok( !$p->can("child_b"), "no child b accessor" );
 isa_ok( $p->child_c, "ChildC" );
 isa_ok( $p->child_d, "ChildD" );
 isa_ok( $p->child_e, "ChildE" );
+isa_ok( $p->child_f, "ChildF" );
 
-ok( !$p->can("child_b"), "no child b accessor" );
-ok( !$p->can("child_f"), "no child f" );
 
 is( $p->parent_method, "p", "parent method" );
 is( $p->child_a->child_a_super_method, "as", "child supermethod" );