From: Tokuhiro Matsuno Date: Tue, 2 Dec 2008 04:36:31 +0000 (+0000) Subject: - added Moose::Util::apply_all_roles X-Git-Tag: 0.19~136^2~90 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=2e92bb89f22acc49ce81b6ec6593d6190559ac45;p=gitmo%2FMouse.git - added Moose::Util::apply_all_roles - added Moose::Meta::Role->get_method_list - added Moose::Meta::Class->get_method_list - copy methods on Moose::Meta::Role->apply --- diff --git a/lib/Mouse/Meta/Class.pm b/lib/Mouse/Meta/Class.pm index 661aad0..5cf70e1 100644 --- a/lib/Mouse/Meta/Class.pm +++ b/lib/Mouse/Meta/Class.pm @@ -63,6 +63,20 @@ sub add_method { *{ $pkg . '::' . $name } = $code; } +# copied from Class::Inspector +sub get_method_list { + my $self = shift; + my $name = $self->name; + + no strict 'refs'; + # Get all the CODE symbol table entries + my @functions = grep !/^meta$/, + grep { /\A[^\W\d]\w*\z/o } + grep { defined &{"${name}::$_"} } + keys %{"${name}::"}; + wantarray ? @functions : \@functions; +} + sub add_attribute { my $self = shift; my $attr = shift; diff --git a/lib/Mouse/Meta/Role.pm b/lib/Mouse/Meta/Role.pm index ebb929f..9037044 100644 --- a/lib/Mouse/Meta/Role.pm +++ b/lib/Mouse/Meta/Role.pm @@ -53,13 +53,41 @@ sub has_attribute { exists $_[0]->{attributes}->{$_[1]} } sub get_attribute_list { keys %{ $_[0]->{attributes} } } sub get_attribute { $_[0]->{attributes}->{$_[1]} } +# copied from Class::Inspector +sub get_method_list { + my $self = shift; + my $name = $self->name; + + no strict 'refs'; + # Get all the CODE symbol table entries + my @functions = grep !/^meta$/, + grep { /\A[^\W\d]\w*\z/o } + grep { defined &{"${name}::$_"} } + keys %{"${name}::"}; + wantarray ? @functions : \@functions; +} + sub apply { my $self = shift; + my $selfname = $self->name; my $class = shift; + my $classname = $class->name; for my $name (@{$self->{required_methods}}) { - unless ($class->name->can($name)) { - confess "'@{[ $self->name ]}' requires the method '$name' to be implemented by '@{[ $class->name ]}'"; + unless ($classname->can($name)) { + confess "'$selfname' requires the method '$name' to be implemented by '$classname'"; + } + } + + { + no strict 'refs'; + for my $name ($self->get_method_list) { + next if $name eq 'has' || $name eq 'requires' || $name eq 'meta' || $name eq 'with' || $name eq 'around' || $name eq 'before' || $name eq 'after' || $name eq 'blessed' || $name eq 'extends' || $name eq 'confess' || $name eq 'excludes'; + if ($classname->can($name)) { + # XXX what's Moose's behavior? + next; + } + *{"${classname}::${name}"} = *{"${selfname}::${name}"}; } } diff --git a/lib/Mouse/Util.pm b/lib/Mouse/Util.pm index a27600b..0c95684 100644 --- a/lib/Mouse/Util.pm +++ b/lib/Mouse/Util.pm @@ -223,6 +223,15 @@ BEGIN { } } +sub apply_all_roles { + my $meta = Mouse::Meta::Class->initialize(shift); + my $role = shift; + confess "Mouse::Util only supports 'apply_all_roles' on individual roles at a time" if @_; + + Mouse::load_class($role); + $role->meta->apply($meta); +} + 1; __END__ diff --git a/t/034-apply_all_roles.t b/t/034-apply_all_roles.t new file mode 100644 index 0000000..557cd5d --- /dev/null +++ b/t/034-apply_all_roles.t @@ -0,0 +1,34 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More tests => 4; +use Mouse::Util ':test'; + +{ + package FooRole; + use Mouse::Role; + sub foo { 'ok1' } +} + +{ + package BarRole; + use Mouse::Role; + sub bar { 'ok2' } +} + +{ + package Baz; + use Mouse; + no Mouse; +} + +throws_ok { Mouse::Util::apply_all_roles('Baz', 'BarRole', 'FooRole') } qr{Mouse::Util only supports 'apply_all_roles' on individual roles at a time}; + +Mouse::Util::apply_all_roles('Baz', 'BarRole'); +Mouse::Util::apply_all_roles('Baz', 'FooRole'); + +my $baz = Baz->new; +is $baz->foo, 'ok1'; +is $baz->bar, 'ok2'; +is join(",", sort $baz->meta->get_method_list), 'bar,foo'; +