Revision history for Perl extension Moose
0.24
+ ~ doc updates ~
+
+ * Moose::Meta::Attribute
+ - added support for roles to be given as parameters
+ to the 'handles' option.
+ - added tests and docs for this
+
* Moose::Meta::Role
- required methods are now fetched using find_method_by_name
so that required methods can come from superclasses
and can typically be ignored). You B<cannot> have a trigger on a read-only
attribute.
-=item I<handles =E<gt> ARRAY | HASH | REGEXP | CODE>
+=item I<handles =E<gt> ARRAY | HASH | REGEXP | ROLE | CODE>
The I<handles> option provides Moose classes with automated delegation features.
This is a pretty complex and powerful option. It accepts many different option
is so that we can determine (at compile time) the method list from the class.
Without an I<isa> this is just not possible.
+=item C<ROLE>
+
+With the role option, you specify the name of a role whose "interface" then
+becomes the list of methods to handle. The "interface" can be defined as; the
+methods of the role and any required methods of the role. It should be noted
+that this does B<not> include any method modifiers or generated attribute
+methods (which is consistent with role composition).
+
=item C<CODE>
This is the option to use when you really want to do something funky. You should
no Moose; # keywords are removed from the Person package
-=head1 MISC.
-
-=head2 What does Moose stand for??
-
-Moose doesn't stand for one thing in particular. However, if you
-want, here are a few of my favorites; feel free to contribute
-more :)
-
-=over 4
-
-=item Make Other Object Systems Envious
-
-=item Makes Object Orientation So Easy
-
-=item Makes Object Orientation Spiffy- Er (sorry ingy)
-
-=item Most Other Object Systems Emasculate
-
-=item Moose Often Ovulate Sorta Early
-
-=item Moose Offers Often Super Extensions
-
-=item Meta Object Orientation Syntax Extensions
-
-=back
-
=head1 CAVEATS
=over 4
This might seem like a restriction, but I am of the opinion that keeping these
two features separate (yet interoperable) actually makes them easy to use, since
their behavior is then easier to predict. Time will tell whether I am right or
-not.
+not (UPDATE: so far so good).
=back
originally, I just ran with it.
=item Thanks to mst & chansen and the whole #moose poose for all the
-ideas/feature-requests/encouragement/bug-finding.
+early ideas/feature-requests/encouragement/bug-finding.
=item Thanks to David "Theory" Wheeler for meta-discussions and spelling fixes.
=over 4
+=item L<http://www.iinteractive.com/moose>
+
+This is the official web home of Moose, it contains links to our public SVN repo
+as well as links to a number of talks and articles on Moose and Moose related
+technologies.
+
=item L<Class::MOP> documentation
=item The #moose channel on irc.perl.org
=item The Moose mailing list - moose@perl.org
-=item L<http://forum2.org/moose/>
+=item Moose stats on ohloh.net - L<http://www.ohloh.net/projects/5788>
+
+=back
+
+=head2 Papers
+
+=over 4
=item L<http://www.cs.utah.edu/plt/publications/oopsla04-gff.pdf>
use Scalar::Util 'blessed', 'weaken', 'reftype';
use Carp 'confess';
-our $VERSION = '0.10';
+our $VERSION = '0.11';
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::Method::Accessor;
sub _canonicalize_handles {
my $self = shift;
my $handles = $self->handles;
- if (ref($handles) eq 'HASH') {
- return %{$handles};
- }
- elsif (ref($handles) eq 'ARRAY') {
- return map { $_ => $_ } @{$handles};
- }
- elsif (ref($handles) eq 'Regexp') {
- ($self->has_type_constraint)
- || confess "Cannot delegate methods based on a RegExpr without a type constraint (isa)";
- return map { ($_ => $_) }
- grep { /$handles/ } $self->_get_delegate_method_list;
- }
- elsif (ref($handles) eq 'CODE') {
- return $handles->($self, $self->_find_delegate_metaclass);
+ if (my $handle_type = ref($handles)) {
+ if ($handle_type eq 'HASH') {
+ return %{$handles};
+ }
+ elsif ($handle_type eq 'ARRAY') {
+ return map { $_ => $_ } @{$handles};
+ }
+ elsif ($handle_type eq 'Regexp') {
+ ($self->has_type_constraint)
+ || confess "Cannot delegate methods based on a RegExpr without a type constraint (isa)";
+ return map { ($_ => $_) }
+ grep { /$handles/ } $self->_get_delegate_method_list;
+ }
+ elsif ($handle_type eq 'CODE') {
+ return $handles->($self, $self->_find_delegate_metaclass);
+ }
+ else {
+ confess "Unable to canonicalize the 'handles' option with $handles";
+ }
}
else {
- confess "Unable to canonicalize the 'handles' option with $handles";
+ my $role_meta = eval { $handles->meta };
+ if ($@) {
+ confess "Unable to canonicalize the 'handles' option with $handles because : $@";
+ }
+
+ (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
+ || confess "Unable to canonicalize the 'handles' option with $handles because ->meta is not a Moose::Meta::Role";
+
+ return map { $_ => $_ } (
+ $role_meta->get_method_list,
+ $role_meta->get_required_method_list
+ );
}
}
use strict;
use warnings;
-use Test::More tests => 46;
+use Test::More tests => 54;
use Test::Exception;
BEGIN {
is($baz_proxy->boo, 'Baz::boo', '... got the right proxied return value');
}
+{
+ package Foo::Bar;
+ use Moose::Role;
+
+ requires 'foo';
+ requires 'bar';
+
+ package Foo::Baz;
+ use Moose;
+
+ sub foo { 'Foo::Baz::FOO' }
+ sub bar { 'Foo::Baz::BAR' }
+ sub baz { 'Foo::Baz::BAZ' }
+
+ package Foo::Thing;
+ use Moose;
+
+ has 'thing' => (
+ is => 'rw',
+ isa => 'Foo::Baz',
+ handles => 'Foo::Bar',
+ );
+
+}
+
+{
+ my $foo = Foo::Thing->new(thing => Foo::Baz->new);
+ isa_ok($foo, 'Foo::Thing');
+ isa_ok($foo->thing, 'Foo::Baz');
+
+ ok($foo->meta->has_method('foo'), '... we have the method we expect');
+ ok($foo->meta->has_method('bar'), '... we have the method we expect');
+ ok(!$foo->meta->has_method('baz'), '... we dont have the method we expect');
+
+ is($foo->foo, 'Foo::Baz::FOO', '... got the right value');
+ is($foo->bar, 'Foo::Baz::BAR', '... got the right value');
+ is($foo->thing->baz, 'Foo::Baz::BAZ', '... got the right value');
+}
+
+
+
+
+