From: Florian Ragwitz Date: Thu, 30 Jul 2009 12:19:50 +0000 (+0200) Subject: Allow applying application_role_summation_class_roles using MetaRole. X-Git-Tag: 0.90~37 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=87f55e332bbf7d977b22ce000fe0f669991bcef4;p=gitmo%2FMoose.git Allow applying application_role_summation_class_roles using MetaRole. --- diff --git a/Makefile.PL b/Makefile.PL index 11fa163..724374b 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -20,7 +20,7 @@ requires 'Sub::Name' => '0'; requires 'Task::Weaken' => '0'; requires 'Try::Tiny' => '0.02'; -test_requires 'Test::More' => '0.77'; +test_requires 'Test::More' => '0.88'; test_requires 'Test::Exception' => '0.27'; if ( -d '.svn' || -d '.git' || $ENV{IS_MAINTAINER} ) { diff --git a/lib/Moose/Util/MetaRole.pm b/lib/Moose/Util/MetaRole.pm index b01c99c..ce13d5d 100644 --- a/lib/Moose/Util/MetaRole.pm +++ b/lib/Moose/Util/MetaRole.pm @@ -57,6 +57,7 @@ sub _make_new_metaclass { application_to_class_class application_to_role_class application_to_instance_class + application_role_summation_class ); my $new_metaclass @@ -75,6 +76,7 @@ sub _make_new_metaclass { application_to_class_class application_to_role_class application_to_instance_class + application_role_summation_class ); return $new_metaclass->reinitialize( $for, %classes ); diff --git a/t/050_metaclasses/030_metarole_combination.t b/t/050_metaclasses/030_metarole_combination.t new file mode 100644 index 0000000..5652a74 --- /dev/null +++ b/t/050_metaclasses/030_metarole_combination.t @@ -0,0 +1,198 @@ +use strict; +use warnings; +use Test::More; + +our @applications; + +{ + package CustomApplication; + use Moose::Role; + after apply_methods => sub { + my ($self, $role, $other) = @_; + $self->apply_custom($role, $other); + }; + + sub apply_custom { + shift; + push @applications, [@_]; + } +} + +{ + package CustomApplication::ToClass; + use Moose::Role; + with 'CustomApplication'; +} + +{ + package CustomApplication::ToRole; + use Moose::Role; + with 'CustomApplication'; +} + +{ + package CustomApplication::ToInstance; + use Moose::Role; + with 'CustomApplication'; +} + +{ + package CustomApplication::Composite; + use Moose::Role; + with 'CustomApplication'; + around apply_custom => sub { + my ($next, $self, $composite, $other) = @_; + for my $role (@{ $composite->get_roles }) { + $self->$next($role, $other); + } + }; +} + +{ + package CustomApplication::Composite::ToClass; + use Moose::Role; + with 'CustomApplication::Composite'; +} + +{ + package CustomApplication::Composite::ToRole; + use Moose::Role; + with 'CustomApplication::Composite'; +} + +{ + package CustomApplication::Composite::ToInstance; + use Moose::Role; + with 'CustomApplication::Composite'; +} + +{ + package Role::Composite; + use Moose::Role; + around apply_params => sub { + my ($next, $self, @args) = @_; + return Moose::Util::MetaRole::apply_metaclass_roles( + for_class => $self->$next(@args), + application_to_class_class_roles => [ 'CustomApplication::Composite::ToClass' ], + application_to_role_class_roles => [ 'CustomApplication::Composite::ToRole' ], + application_to_instance_class_roles => [ 'CustomApplication::Composite::ToInstance' ], + ); + }; +} + +{ + package Role::WithCustomApplication; + use Moose::Role; + has '+composition_class_roles' => ( + default => [ 'Role::Composite' ], + ); +} + +{ + package CustomRole; + Moose::Exporter->setup_import_methods( + also => 'Moose::Role', + ); + + sub init_meta { + my ($self, %options) = @_; + return Moose::Util::MetaRole::apply_metaclass_roles( + for_class => Moose::Role->init_meta(%options), + metaclass_roles => [ 'Role::WithCustomApplication' ], + application_to_class_class_roles => [ 'CustomApplication::ToClass' ], + application_to_role_class_roles => [ 'CustomApplication::ToRole' ], + application_to_instance_class_roles => [ 'CustomApplication::ToInstance' ], + ); + } +} + +{ + package My::Role::Normal; + use Moose::Role; +} + +{ + package My::Role::Special; + CustomRole->import; +} + +ok(My::Role::Normal->meta->isa('Moose::Meta::Role'), "sanity check"); +ok(My::Role::Special->meta->isa('Moose::Meta::Role'), "using custom application roles does not change the role metaobject's class"); +ok(My::Role::Special->meta->meta->does_role('Role::WithCustomApplication'), "the role's metaobject has custom applications"); +is_deeply(My::Role::Special->meta->composition_class_roles, ['Role::Composite'], "the role knows about the specified composition class"); + +{ + package Foo; + use Moose; + local @applications; + with 'My::Role::Special'; + ::is(@applications, 1, 'one role application'); + ::is($applications[0]->[0]->name, 'My::Role::Special', "the application's first role was My::Role::Special'"); + ::is($applications[0]->[1]->name, 'Foo', "the application provided an additional role"); +} + +{ + package Bar; + use Moose::Role; + local @applications; + with 'My::Role::Special'; + ::is(@applications, 1); + ::is($applications[0]->[0]->name, 'My::Role::Special'); + ::is($applications[0]->[1]->name, 'Bar'); +} + +{ + package Baz; + use Moose; + my $i = Baz->new; + local @applications; + My::Role::Special->meta->apply($i); + ::is(@applications, 1); + ::is($applications[0]->[0]->name, 'My::Role::Special'); + ::ok($applications[0]->[1]->is_anon_class); + ::ok($applications[0]->[1]->name->isa('Baz')); +} + +{ + package Corge; + use Moose; + local @applications; + with 'My::Role::Normal', 'My::Role::Special'; + ::is(@applications, 2); + ::is($applications[0]->[0]->name, 'My::Role::Normal'); + ::is($applications[0]->[1]->name, 'Corge'); + ::is($applications[1]->[0]->name, 'My::Role::Special'); + ::is($applications[1]->[1]->name, 'Corge'); +} + +{ + package Thud; + use Moose::Role; + local @applications; + with 'My::Role::Normal', 'My::Role::Special'; + ::is(@applications, 2); + ::is($applications[0]->[0]->name, 'My::Role::Normal'); + ::is($applications[0]->[1]->name, 'Thud'); + ::is($applications[1]->[0]->name, 'My::Role::Special'); + ::is($applications[1]->[1]->name, 'Thud'); +} + +{ + package Garply; + use Moose; + my $i = Garply->new; + local @applications; + Moose::Meta::Role->combine( + ['My::Role::Normal' => undef], + ['My::Role::Special' => undef], + )->apply($i); + ::is(@applications, 2); + ::is($applications[0]->[0]->name, 'My::Role::Normal'); + ::ok($applications[0]->[1]->is_anon_class); + ::ok($applications[0]->[1]->name->isa('Garply')); + ::is($applications[1]->[0]->name, 'My::Role::Special'); + ::ok($applications[1]->[1]->is_anon_class); + ::ok($applications[1]->[1]->name->isa('Garply')); +} + +done_testing;