Add role_for_combination for MXRP
Shawn M Moore [Sun, 10 May 2009 03:34:15 +0000 (23:34 -0400)]
Changes
lib/Moose/Meta/Role.pm
t/030_roles/040_role_for_combination.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 4427154..30d8367 100644 (file)
--- a/Changes
+++ b/Changes
@@ -28,6 +28,10 @@ for, noteworthy changes.
       - Fix metaclass incompatibility errors when extending a vanilla perl
         class which isa Moose class with a metaclass role applied (t0m)
 
+    * Moose::Meta::Role
+      - Add a role-combination hook, role_for_combination, for the
+        benefit of MooseX::Role::Parameterized (Sartak)
+
 0.77 Sat, May 2, 2009
     * Moose::Meta::Role
       - Add explicit use of Devel::GlobalDestruction and Sub::Name
index 65de5aa..d38ec2a 100644 (file)
@@ -446,6 +446,11 @@ sub apply {
     }
 }
 
+sub role_for_combination {
+    my ($self, $params) = @_;
+    return $self;
+}
+
 sub combine {
     my ($class, @role_specs) = @_;
 
@@ -454,10 +459,14 @@ sub combine {
 
     my (@roles, %role_params);
     while (@role_specs) {
-        my ($role, $params) = @{ splice @role_specs, 0, 1 };
-        push @roles => Class::MOP::class_of($role);
+        my ($role_name, $params) = @{ splice @role_specs, 0, 1 };
+        my $requested_role = Class::MOP::class_of($role_name);
+
+        my $actual_role = $requested_role->role_for_combination($params);
+        push @roles => $actual_role;
+
         next unless defined $params;
-        $role_params{$role} = $params;
+        $role_params{$actual_role->name} = $params;
     }
 
     my $c = Moose::Meta::Role::Composite->new(roles => \@roles);
@@ -744,6 +753,12 @@ and C<alias> keys to control how methods are composed from the role.
 The return value is a new L<Moose::Meta::Role::Composite> that
 represents the combined roles.
 
+=item B<< Moose::Meta::Role->role_for_combination($options) >>
+
+This is a hook for incorporating role-combination parameters. This
+method returns a role metaobject (by default the invocant role) to be
+used for the combination.
+
 =item B<< Moose::Meta::Role->create($name, %options) >>
 
 This method is identical to the L<Moose::Meta::Class> C<create>
diff --git a/t/030_roles/040_role_for_combination.t b/t/030_roles/040_role_for_combination.t
new file mode 100644 (file)
index 0000000..302e334
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+my $OPTS;
+do {
+    package My::Singleton::Role;
+    use Moose::Role;
+
+    sub foo { 'My::Singleton::Role' }
+
+    package My::Role::Metaclass;
+    use Moose;
+    BEGIN { extends 'Moose::Meta::Role' };
+
+    sub role_for_combination {
+        my ($self, $opts) = @_;
+        $OPTS = $opts;
+        return My::Singleton::Role->meta;
+    }
+
+    package My::Special::Role;
+    use Moose::Role -metaclass => 'My::Role::Metaclass';
+
+    sub foo { 'My::Special::Role' }
+
+    package My::Usual::Role;
+    use Moose::Role;
+
+    sub bar { 'My::Usual::Role' }
+
+    package My::Class;
+    use Moose;
+
+    with (
+        'My::Special::Role' => { number => 1 },
+        'My::Usual::Role' => { number => 2 },
+    );
+};
+
+is(My::Class->foo, 'My::Singleton::Role', 'role_for_combination applied');
+is(My::Class->bar, 'My::Usual::Role', 'collateral role');
+is_deeply($OPTS, { number => 1 });
+