Bump to 0.56
[gitmo/Moose.git] / lib / Moose / Role.pm
CommitLineData
e185c027 1
2package Moose::Role;
3
4use strict;
5use warnings;
6
e65dccbc 7use Scalar::Util 'blessed';
cc5e6b6f 8use Carp 'confess', 'croak';
e185c027 9
c4538447 10use Data::OptList;
2d562421 11use Sub::Exporter;
12
a94188ac 13our $VERSION = '0.56';
d44714be 14our $AUTHORITY = 'cpan:STEVAN';
e185c027 15
d7d8a8c7 16use Moose ();
17use Moose::Util ();
e65dccbc 18
e185c027 19use Moose::Meta::Role;
7eaef7ad 20use Moose::Util::TypeConstraints;
e185c027 21
2d562421 22{
23 my ( $CALLER, %METAS );
24
25 sub _find_meta {
7eaef7ad 26 my $role = $CALLER;
2d562421 27
7eaef7ad 28 return $METAS{$role} if exists $METAS{$role};
fb1e11d5 29
7eaef7ad 30 # make a subtype for each Moose class
e324865b 31 role_type $role unless find_type_constraint($role);
2d562421 32
fb1e11d5 33 my $meta;
34 if ($role->can('meta')) {
35 $meta = $role->meta();
36 (blessed($meta) && $meta->isa('Moose::Meta::Role'))
68efb014 37 || confess "You already have a &meta function, but it does not return a Moose::Meta::Role";
fb1e11d5 38 }
39 else {
40 $meta = Moose::Meta::Role->initialize($role);
41 $meta->alias_method('meta' => sub { $meta });
42 }
2d562421 43
7eaef7ad 44 return $METAS{$role} = $meta;
2d562421 45 }
fb1e11d5 46
47
48 my %exports = (
2d562421 49 extends => sub {
50 my $meta = _find_meta();
1b2aea39 51 return Class::MOP::subname('Moose::Role::extends' => sub {
685c7fac 52 croak "Roles do not currently support 'extends'"
1b2aea39 53 });
fb1e11d5 54 },
55 with => sub {
56 my $meta = _find_meta();
1b2aea39 57 return Class::MOP::subname('Moose::Role::with' => sub (@) {
d7d8a8c7 58 Moose::Util::apply_all_roles($meta, @_)
1b2aea39 59 });
fb1e11d5 60 },
2d562421 61 requires => sub {
62 my $meta = _find_meta();
1b2aea39 63 return Class::MOP::subname('Moose::Role::requires' => sub (@) {
cc5e6b6f 64 croak "Must specify at least one method" unless @_;
2d562421 65 $meta->add_required_methods(@_);
1b2aea39 66 });
fb1e11d5 67 },
d79e62fd 68 excludes => sub {
69 my $meta = _find_meta();
1b2aea39 70 return Class::MOP::subname('Moose::Role::excludes' => sub (@) {
cc5e6b6f 71 croak "Must specify at least one role" unless @_;
d79e62fd 72 $meta->add_excluded_roles(@_);
1b2aea39 73 });
fb1e11d5 74 },
2d562421 75 has => sub {
76 my $meta = _find_meta();
1b2aea39 77 return Class::MOP::subname('Moose::Role::has' => sub ($;%) {
1580432f 78 my $name = shift;
cc5e6b6f 79 croak 'Usage: has \'name\' => ( key => value, ... )' if @_ == 1;
1580432f 80 my %options = @_;
81 my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
82 $meta->add_attribute( $_, %options ) for @$attrs;
1b2aea39 83 });
fb1e11d5 84 },
2d562421 85 before => sub {
86 my $meta = _find_meta();
1b2aea39 87 return Class::MOP::subname('Moose::Role::before' => sub (@&) {
0558683c 88 my $code = pop @_;
401cb5a6 89 do {
cc5e6b6f 90 croak "Moose::Role do not currently support "
401cb5a6 91 . ref($_)
92 . " references for before method modifiers"
93 if ref $_;
94 $meta->add_before_method_modifier($_, $code)
95 } for @_;
1b2aea39 96 });
fb1e11d5 97 },
2d562421 98 after => sub {
99 my $meta = _find_meta();
1b2aea39 100 return Class::MOP::subname('Moose::Role::after' => sub (@&) {
fb1e11d5 101 my $code = pop @_;
401cb5a6 102 do {
cc5e6b6f 103 croak "Moose::Role do not currently support "
401cb5a6 104 . ref($_)
105 . " references for after method modifiers"
106 if ref $_;
107 $meta->add_after_method_modifier($_, $code)
108 } for @_;
1b2aea39 109 });
fb1e11d5 110 },
2d562421 111 around => sub {
112 my $meta = _find_meta();
1b2aea39 113 return Class::MOP::subname('Moose::Role::around' => sub (@&) {
fb1e11d5 114 my $code = pop @_;
401cb5a6 115 do {
cc5e6b6f 116 croak "Moose::Role do not currently support "
401cb5a6 117 . ref($_)
118 . " references for around method modifiers"
119 if ref $_;
120 $meta->add_around_method_modifier($_, $code)
121 } for @_;
1b2aea39 122 });
fb1e11d5 123 },
3f9e4b0a 124 # see Moose.pm for discussion
fb1e11d5 125 super => sub {
401cb5a6 126 return Class::MOP::subname('Moose::Role::super' => sub {
127 return unless $Moose::SUPER_BODY; $Moose::SUPER_BODY->(@Moose::SUPER_ARGS)
128 });
2d562421 129 },
130 override => sub {
131 my $meta = _find_meta();
1b2aea39 132 return Class::MOP::subname('Moose::Role::override' => sub ($&) {
0558683c 133 my ($name, $code) = @_;
134 $meta->add_override_method_modifier($name, $code);
1b2aea39 135 });
fb1e11d5 136 },
2d562421 137 inner => sub {
138 my $meta = _find_meta();
1b2aea39 139 return Class::MOP::subname('Moose::Role::inner' => sub {
cc5e6b6f 140 croak "Moose::Role cannot support 'inner'";
1b2aea39 141 });
fb1e11d5 142 },
2d562421 143 augment => sub {
144 my $meta = _find_meta();
1b2aea39 145 return Class::MOP::subname('Moose::Role::augment' => sub {
cc5e6b6f 146 croak "Moose::Role cannot support 'augment'";
1b2aea39 147 });
fb1e11d5 148 },
2d562421 149 confess => sub {
150 return \&Carp::confess;
151 },
152 blessed => sub {
153 return \&Scalar::Util::blessed;
fb1e11d5 154 }
155 );
2d562421 156
fb1e11d5 157 my $exporter = Sub::Exporter::build_exporter({
2d562421 158 exports => \%exports,
159 groups => {
160 default => [':all']
161 }
162 });
fb1e11d5 163
2d562421 164 sub import {
fc9a40d7 165 $CALLER =
166 ref $_[1] && defined $_[1]->{into} ? $_[1]->{into}
167 : ref $_[1]
168 && defined $_[1]->{into_level} ? caller( $_[1]->{into_level} )
169 : caller();
170
86dd5d11 171 # this works because both pragmas set $^H (see perldoc perlvar)
172 # which affects the current compilation - i.e. the file who use'd
173 # us - which is why we don't need to do anything special to make
174 # it affect that file rather than this one (which is already compiled)
fb1e11d5 175
c235cd98 176 strict->import;
fb1e11d5 177 warnings->import;
2d562421 178
179 # we should never export to main
180 return if $CALLER eq 'main';
181
182 goto $exporter;
183 };
184
d31f9614 185 sub unimport {
186 no strict 'refs';
fd75e12b 187 my $class = Moose::_get_caller(@_);
d31f9614 188
189 # loop through the exports ...
190 foreach my $name ( keys %exports ) {
191
192 # if we find one ...
193 if ( defined &{ $class . '::' . $name } ) {
194 my $keyword = \&{ $class . '::' . $name };
195
196 # make sure it is from Moose::Role
197 my ($pkg_name) = Class::MOP::get_code_info($keyword);
198 next if $pkg_name ne 'Moose::Role';
199
200 # and if it is from Moose::Role then undef the slot
201 delete ${ $class . '::' }{$name};
202 }
203 }
204 }
e185c027 205}
206
2071;
208
209__END__
210
211=pod
212
213=head1 NAME
214
215Moose::Role - The Moose Role
216
76d37e5a 217=head1 SYNOPSIS
218
219 package Eq;
85424612 220 use Moose::Role; # automatically turns on strict and warnings
fb1e11d5 221
e46edf94 222 requires 'equal';
fb1e11d5 223
224 sub no_equal {
76d37e5a 225 my ($self, $other) = @_;
226 !$self->equal($other);
227 }
fb1e11d5 228
76d37e5a 229 # ... then in your classes
fb1e11d5 230
76d37e5a 231 package Currency;
85424612 232 use Moose; # automatically turns on strict and warnings
fb1e11d5 233
76d37e5a 234 with 'Eq';
fb1e11d5 235
76d37e5a 236 sub equal {
237 my ($self, $other) = @_;
bdabd620 238 $self->as_float == $other->as_float;
76d37e5a 239 }
240
e185c027 241=head1 DESCRIPTION
242
85424612 243Role support in Moose is pretty solid at this point. However, the best
244documentation is still the the test suite. It is fairly safe to assume Perl 6
245style behavior and then either refer to the test suite, or ask questions on
246#moose if something doesn't quite do what you expect.
d44714be 247
85424612 248We are planning writing some more documentation in the near future, but nothing
249is ready yet, sorry.
76d37e5a 250
2c0cbef7 251=head1 EXPORTED FUNCTIONS
252
85424612 253Moose::Role currently supports all of the functions that L<Moose> exports, but
254differs slightly in how some items are handled (see L<CAVEATS> below for
255details).
76d37e5a 256
85424612 257Moose::Role also offers two role-specific keyword exports:
e185c027 258
259=over 4
260
2c0cbef7 261=item B<requires (@method_names)>
76d37e5a 262
fb1e11d5 263Roles can require that certain methods are implemented by any class which
85424612 264C<does> the role.
9e93dd19 265
2c0cbef7 266=item B<excludes (@role_names)>
267
9e93dd19 268Roles can C<exclude> other roles, in effect saying "I can never be combined
fb1e11d5 269with these C<@role_names>". This is a feature which should not be used
85424612 270lightly.
9e93dd19 271
2c0cbef7 272=back
273
d31f9614 274=head2 B<unimport>
275
276Moose::Role offers a way to remove the keywords it exports, through the
277C<unimport> method. You simply have to say C<no Moose::Role> at the bottom of
278your code for this to work.
279
2c0cbef7 280=head1 CAVEATS
281
85424612 282Role support has only a few caveats:
2c0cbef7 283
284=over 4
76d37e5a 285
76d37e5a 286=item *
287
fb1e11d5 288Roles cannot use the C<extends> keyword; it will throw an exception for now.
289The same is true of the C<augment> and C<inner> keywords (not sure those
290really make sense for roles). All other Moose keywords will be I<deferred>
85424612 291so that they can be applied to the consuming class.
76d37e5a 292
fb1e11d5 293=item *
2c0cbef7 294
85424612 295Role composition does its best to B<not> be order-sensitive when it comes to
296conflict resolution and requirements detection. However, it is order-sensitive
297when it comes to method modifiers. All before/around/after modifiers are
298included whenever a role is composed into a class, and then applied in the order
299in which the roles are used. This also means that there is no conflict for
300before/around/after modifiers.
2c0cbef7 301
85424612 302In most cases, this will be a non-issue; however, it is something to keep in
303mind when using method modifiers in a role. You should never assume any
2c0cbef7 304ordering.
305
306=item *
307
fb1e11d5 308The C<requires> keyword currently only works with actual methods. A method
309modifier (before/around/after and override) will not count as a fufillment
2c0cbef7 310of the requirement, and neither will an autogenerated accessor for an attribute.
311
85424612 312It is likely that attribute accessors will eventually be allowed to fufill those
313requirements, or we will introduce a C<requires_attr> keyword of some kind
314instead. This decision has not yet been finalized.
2c0cbef7 315
e185c027 316=back
317
318=head1 BUGS
319
fb1e11d5 320All complex software has bugs lurking in it, and this module is no
e185c027 321exception. If you find a bug please either email me, or add the bug
322to cpan-RT.
323
324=head1 AUTHOR
325
326Stevan Little E<lt>stevan@iinteractive.comE<gt>
327
db1ab48d 328Christian Hansen E<lt>chansen@cpan.orgE<gt>
98aae381 329
e185c027 330=head1 COPYRIGHT AND LICENSE
331
778db3ac 332Copyright 2006-2008 by Infinity Interactive, Inc.
e185c027 333
334L<http://www.iinteractive.com>
335
336This library is free software; you can redistribute it and/or modify
fb1e11d5 337it under the same terms as Perl itself.
e185c027 338
68117c45 339=cut