die wrap with prefix for attribute isa
[gitmo/Moo.git] / lib / Moo.pm
CommitLineData
b1eebd55 1package Moo;
6c74d087 2
3use strictures 1;
b1eebd55 4use Moo::_Utils;
e0e12d16 5use B 'perlstring';
a41e15c3 6use Sub::Defer ();
6c74d087 7
86e043d2 8our $VERSION = '0.091014'; # 0.91.14
6d71fae7 9$VERSION = eval $VERSION;
10
c2cb1fed 11require Moo::sification;
8c46a8f6 12
14f32032 13our %MAKERS;
14
108f8ddc 15sub _install_tracked {
16 my ($target, $name, $code) = @_;
17 $MAKERS{$target}{exports}{$name} = $code;
18 _install_coderef "${target}::${name}" => "Moo::${name}" => $code;
19}
20
6c74d087 21sub import {
22 my $target = caller;
a16d301e 23 my $class = shift;
de3d4906 24 strictures->import;
1ba11455 25 return if $MAKERS{$target}; # already exported into this package
108f8ddc 26 $MAKERS{$target} = {};
27 _install_tracked $target => extends => sub {
48a51428 28 $class->_set_superclasses($target, @_);
6c49212f 29 $class->_maybe_reset_handlemoose($target);
3d49ee27 30 return;
6c74d087 31 };
108f8ddc 32 _install_tracked $target => with => sub {
faa9ce11 33 require Moo::Role;
6067158c 34 Moo::Role->apply_roles_to_package($target, @_);
6c49212f 35 $class->_maybe_reset_handlemoose($target);
6c74d087 36 };
108f8ddc 37 _install_tracked $target => has => sub {
14f32032 38 my ($name, %spec) = @_;
a16d301e 39 $class->_constructor_maker_for($target)
40 ->register_attribute_specs($name, \%spec);
02e9ef74 41 $class->_accessor_maker_for($target)
42 ->generate_method($target, $name, \%spec);
6c49212f 43 $class->_maybe_reset_handlemoose($target);
3d49ee27 44 return;
14f32032 45 };
6c74d087 46 foreach my $type (qw(before after around)) {
108f8ddc 47 _install_tracked $target => $type => sub {
faa9ce11 48 require Class::Method::Modifiers;
6c74d087 49 _install_modifier($target, $type, @_);
3d49ee27 50 return;
6c74d087 51 };
52 }
53 {
54 no strict 'refs';
55 @{"${target}::ISA"} = do {
faa9ce11 56 require Moo::Object; ('Moo::Object');
6c74d087 57 } unless @{"${target}::ISA"};
58 }
3362e41c 59 if ($INC{'Moo/HandleMoose.pm'}) {
60 Moo::HandleMoose::inject_fake_metaclass_for($target);
61 }
6c74d087 62}
63
108f8ddc 64sub unimport {
65 my $target = caller;
66 _unimport_coderefs($target, $MAKERS{$target});
67}
68
48a51428 69sub _set_superclasses {
88aaa04a 70 my $class = shift;
71 my $target = shift;
72 for (@_) {
73 _load_module($_);
74 if ($INC{"Role/Tiny.pm"} && $Role::Tiny::INFO{$_}) {
75 require Carp;
76 Carp::croak("Can't extend role '$_'");
48a51428 77 }
88aaa04a 78 }
79 # Can't do *{...} = \@_ or 5.10.0's mro.pm stops seeing @ISA
80 @{*{_getglob("${target}::ISA")}{ARRAY}} = @_;
81 if (my $old = delete $Moo::MAKERS{$target}{constructor}) {
82 delete _getstash($target)->{new};
83 Moo->_constructor_maker_for($target)
84 ->register_attribute_specs(%{$old->all_attribute_specs});
85 }
86 no warnings 'once'; # piss off. -- mst
87 $Moo::HandleMoose::MOUSE{$target} = [
88 grep defined, map Mouse::Util::find_meta($_), @_
89 ] if $INC{"Mouse.pm"};
48a51428 90}
91
6c49212f 92sub _maybe_reset_handlemoose {
93 my ($class, $target) = @_;
94 if ($INC{"Moo/HandleMoose.pm"}) {
95 Moo::HandleMoose::maybe_reinject_fake_metaclass_for($target);
96 }
97}
98
02e9ef74 99sub _accessor_maker_for {
100 my ($class, $target) = @_;
101 return unless $MAKERS{$target};
102 $MAKERS{$target}{accessor} ||= do {
103 my $maker_class = do {
104 if (my $m = do {
105 if (my $defer_target =
106 (Sub::Defer::defer_info($target->can('new'))||[])->[0]
107 ) {
108 my ($pkg) = ($defer_target =~ /^(.*)::[^:]+$/);
109 $MAKERS{$pkg} && $MAKERS{$pkg}{accessor};
110 } else {
111 undef;
112 }
113 }) {
114 ref($m);
115 } else {
116 require Method::Generate::Accessor;
117 'Method::Generate::Accessor'
118 }
119 };
120 $maker_class->new;
121 }
122}
123
a16d301e 124sub _constructor_maker_for {
c4570291 125 my ($class, $target, $select_super) = @_;
a16d301e 126 return unless $MAKERS{$target};
127 $MAKERS{$target}{constructor} ||= do {
faa9ce11 128 require Method::Generate::Constructor;
129 require Sub::Defer;
c4570291 130 my ($moo_constructor, $con);
de5c0e53 131
c4570291 132 if ($select_super && $MAKERS{$select_super}) {
133 $moo_constructor = 1;
134 $con = $MAKERS{$select_super}{constructor};
135 } else {
de5c0e53 136 my $t_new = $target->can('new');
c4570291 137 if ($t_new) {
138 if ($t_new == Moo::Object->can('new')) {
139 $moo_constructor = 1;
140 } elsif (my $defer_target = (Sub::Defer::defer_info($t_new)||[])->[0]) {
141 my ($pkg) = ($defer_target =~ /^(.*)::[^:]+$/);
142 if ($MAKERS{$pkg}) {
143 $moo_constructor = 1;
144 $con = $MAKERS{$pkg}{constructor};
145 }
146 }
147 } else {
148 $moo_constructor = 1; # no other constructor, make a Moo one
149 }
de5c0e53 150 };
02e9ef74 151 ($con ? ref($con) : 'Method::Generate::Constructor')
a16d301e 152 ->new(
153 package => $target,
02e9ef74 154 accessor_generator => $class->_accessor_maker_for($target),
53875e2c 155 construction_string => (
156 $moo_constructor
157 ? ($con ? $con->construction_string : undef)
158 : ('$class->'.$target.'::SUPER::new(@_)')
e0e12d16 159 ),
76ab3977 160 subconstructor_handler => (
161 ' if ($Moo::MAKERS{$class}) {'."\n"
162 .' '.$class.'->_constructor_maker_for($class,'.perlstring($target).');'."\n"
163 .' return $class->new(@_)'.";\n"
346177ba 164 .' } elsif ($INC{"Moose.pm"} and my $meta = Class::MOP::get_metaclass_by_name($class)) {'."\n"
165 .' return $meta->new_object(@_);'."\n"
76ab3977 166 .' }'."\n"
e0e12d16 167 ),
a16d301e 168 )
169 ->install_delayed
de5c0e53 170 ->register_attribute_specs(%{$con?$con->all_attribute_specs:{}})
a16d301e 171 }
172}
173
6c74d087 1741;
a17be455 175=pod
176
177=encoding utf-8
8146585e 178
505f8b7a 179=head1 NAME
180
181Moo - Minimalist Object Orientation (with Moose compatiblity)
182
8146585e 183=head1 SYNOPSIS
184
185 package Cat::Food;
186
187 use Moo;
188 use Sub::Quote;
189
190 sub feed_lion {
191 my $self = shift;
192 my $amount = shift || 1;
193
194 $self->pounds( $self->pounds - $amount );
195 }
196
197 has taste => (
198 is => 'ro',
199 );
200
201 has brand => (
202 is => 'ro',
203 isa => sub {
204 die "Only SWEET-TREATZ supported!" unless $_[0] eq 'SWEET-TREATZ'
205 },
206);
207
208 has pounds => (
209 is => 'rw',
210 isa => quote_sub q{ die "$_[0] is too much cat food!" unless $_[0] < 15 },
211 );
212
213 1;
214
215and else where
216
217 my $full = Cat::Food->new(
218 taste => 'DELICIOUS.',
219 brand => 'SWEET-TREATZ',
220 pounds => 10,
221 );
222
223 $full->feed_lion;
224
225 say $full->pounds;
226
227=head1 DESCRIPTION
228
229This module is an extremely light-weight, high-performance L<Moose> replacement.
230It also avoids depending on any XS modules to allow simple deployments. The
231name C<Moo> is based on the idea that it provides almost -but not quite- two
232thirds of L<Moose>.
233
234Unlike C<Mouse> this module does not aim at full L<Moose> compatibility. See
235L</INCOMPATIBILITIES> for more details.
236
5d5bb71d 237=head1 WHY MOO EXISTS
238
239If you want a full object system with a rich Metaprotocol, L<Moose> is
240already wonderful.
241
242I've tried several times to use L<Mouse> but it's 3x the size of Moo and
243takes longer to load than most of my Moo based CGI scripts take to run.
244
245If you don't want L<Moose>, you don't want "less metaprotocol" like L<Mouse>,
246you want "as little as possible" - which means "no metaprotocol", which is
247what Moo provides.
248
249By Moo 1.0 I intend to have Moo's equivalent of L<Any::Moose> built in -
250if Moose gets loaded, any Moo class or role will act as a Moose equivalent
251if treated as such.
252
253Hence - Moo exists as its name - Minimal Object Orientation - with a pledge
254to make it smooth to upgrade to L<Moose> when you need more than minimal
255features.
256
a297a9ab 257=head1 Moo and Moose
1fce5bc9 258
259If L<Moo> detects L<Moose> being loaded, it will automatically register
260metaclasses for your L<Moo> and L<Moo::Role> packages, so you should be able
a297a9ab 261to use them in L<Moose> code without anybody ever noticing you aren't using
1fce5bc9 262L<Moose> everywhere.
263
a297a9ab 264Extending a L<Moose> class or consuming a L<Moose::Role> will also work.
1fce5bc9 265
a297a9ab 266So will extending a L<Mouse> class or consuming a L<Mouse::Role> - but note
267that we don't provide L<Mouse> metaclasses or metaroles so the other way
268around doesn't work. This feature exists for L<Any::Moose> users porting to
269L<Moo>, enabling L<Mouse> users to use L<Moo> classes is not a priority for us.
c100c04c 270
660f3db2 271This means that there is no need for anything like L<Any::Moose> for Moo
c100c04c 272code - Moo and Moose code should simply interoperate without problem. To
273handle L<Mouse> code, you'll likely need an empty Moo role or class consuming
274or extending the L<Mouse> stuff since it doesn't register true L<Moose>
275metaclasses like we do.
660f3db2 276
1fce5bc9 277If you need to disable the metaclass creation, add:
278
279 no Moo::sification;
280
281to your code before Moose is loaded, but bear in mind that this switch is
a297a9ab 282currently global and turns the mechanism off entirely so don't put this
283in library code.
1fce5bc9 284
8146585e 285=head1 IMPORTED METHODS
286
287=head2 new
288
289 Foo::Bar->new( attr1 => 3 );
290
291or
292
293 Foo::Bar->new({ attr1 => 3 });
294
2e575bcd 295=head2 BUILDARGS
296
f2eac33e 297 sub BUILDARGS {
a17be455 298 my ( $class, @args ) = @_;
299
300 unshift @args, "attr1" if @args % 2 == 1;
301
f2eac33e 302 return { @args };
a17be455 303 };
304
305 Foo::Bar->new( 3 );
306
307The default implementation of this method accepts a hash or hash reference of
308named parameters. If it receives a single argument that isn't a hash reference
309it throws an error.
310
311You can override this method in your class to handle other types of options
312passed to the constructor.
313
314This method should always return a hash reference of named options.
2e575bcd 315
2d00f3d6 316=head2 BUILD
8146585e 317
2d00f3d6 318Define a C<BUILD> method on your class and the constructor will automatically
319call the C<BUILD> method from parent down to child after the object has
320been instantiated. Typically this is used for object validation or possibly
321logging.
8146585e 322
2d00f3d6 323=head2 DEMOLISH
c2cc003f 324
debb3fcd 325If you have a C<DEMOLISH> method anywhere in your inheritance hierarchy,
326a C<DESTROY> method is created on first object construction which will call
c2cc003f 327C<< $instance->DEMOLISH($in_global_destruction) >> for each C<DEMOLISH>
debb3fcd 328method from child upwards to parents.
329
330Note that the C<DESTROY> method is created on first construction of an object
331of your class in order to not add overhead to classes without C<DEMOLISH>
332methods; this may prove slightly surprising if you try and define your own.
c2cc003f 333
8146585e 334=head2 does
335
336 if ($foo->does('Some::Role1')) {
337 ...
338 }
339
340Returns true if the object composes in the passed role.
341
342=head1 IMPORTED SUBROUTINES
343
344=head2 extends
345
346 extends 'Parent::Class';
347
2e575bcd 348Declares base class. Multiple superclasses can be passed for multiple
349inheritance (but please use roles instead).
350
351Calling extends more than once will REPLACE your superclasses, not add to
352them like 'use base' would.
8146585e 353
354=head2 with
355
356 with 'Some::Role1';
8146585e 357
f9755246 358or
359
360 with 'Some::Role1', 'Some::Role2';
361
362Composes one or more L<Moo::Role> (or L<Role::Tiny>) roles into the current
363class. An error will be raised if these roles have conflicting methods.
8146585e 364
365=head2 has
366
367 has attr => (
368 is => 'ro',
369 );
370
371Declares an attribute for the class.
372
373The options for C<has> are as follows:
374
375=over 2
376
377=item * is
378
6577509a 379B<required>, may be C<ro>, C<lazy>, C<rwp> or C<rw>.
71db76ce 380
381C<ro> generates an accessor that dies if you attempt to write to it - i.e.
382a getter only - by defaulting C<reader> to the name of the attribute.
383
71db76ce 384C<lazy> generates a reader like C<ro>, but also sets C<lazy> to 1 and
385C<builder> to C<_build_${attribute_name}> to allow on-demand generated
386attributes. This feature was my attempt to fix my incompetence when
387originally designing C<lazy_build>, and is also implemented by
388L<MooseX::AttributeShortcuts>.
389
390C<rwp> generates a reader like C<ro>, but also sets C<writer> to
391C<_set_${attribute_name}> for attributes that are designed to be written
392from inside of the class, but read-only from outside.
393This feature comes from L<MooseX::AttributeShortcuts>.
8146585e 394
6577509a 395C<rw> generates a normal getter/setter by defaulting C<accessor> to the
396name of the attribute.
397
8146585e 398=item * isa
399
400Takes a coderef which is meant to validate the attribute. Unlike L<Moose> Moo
401does not include a basic type system, so instead of doing C<< isa => 'Num' >>,
402one should do
403
404 isa => quote_sub q{
405 die "$_[0] is not a number!" unless looks_like_number $_[0]
406 },
407
408L<Sub::Quote aware|/SUB QUOTE AWARE>
409
c4074652 410Since L<Moo> does B<not> run the C<isa> check before C<coerce> if a coercion
411subroutine has been supplied, C<isa> checks are not structural to your code
412and can, if desired, be omitted on non-debug builds (although if this results
413in an uncaught bug causing your program to break, the L<Moo> authors guarantee
414nothing except that you get to keep both halves).
415
71db76ce 416If you want L<MooseX::Types> style named types, look at
417L<MooX::Types::MooseLike>.
418
419To cause your C<isa> entries to be automatically mapped to named
420L<Moose::Meta::TypeConstraint> objects (rather than the default behaviour
421of creating an anonymous type), set:
422
423 $Moo::HandleMoose::TYPE_MAP{$isa_coderef} = sub {
424 require MooseX::Types::Something;
425 return MooseX::Types::Something::TypeName();
426 };
427
428Note that this example is purely illustrative; anything that returns a
429L<Moose::Meta::TypeConstraint> object or something similar enough to it to
430make L<Moose> happy is fine.
431
8146585e 432=item * coerce
433
434Takes a coderef which is meant to coerce the attribute. The basic idea is to
435do something like the following:
436
437 coerce => quote_sub q{
438 $_[0] + 1 unless $_[0] % 2
439 },
440
c4074652 441Note that L<Moo> will always fire your coercion - this is to permit
442isa entries to be used purely for bug trapping, whereas coercions are
443always structural to your code. We do, however, apply any supplied C<isa>
444check after the coercion has run to ensure that it returned a valid value.
8146585e 445
23a3e34e 446L<Sub::Quote aware|/SUB QUOTE AWARE>
2e575bcd 447
e1efec09 448=item * handles
449
450Takes a string
451
69673ca7 452 handles => 'RobotRole'
453
454Where C<RobotRole> is a role (L<Moo::Role>) that defines an interface which
455becomes the list of methods to handle.
e1efec09 456
457Takes a list of methods
458
459 handles => [ qw( one two ) ]
460
461Takes a hashref
462
463 handles => {
464 un => 'one',
465 }
466
8146585e 467=item * trigger
468
6fe5100d 469Takes a coderef which will get called any time the attribute is set. This
470includes the constructor. Coderef will be invoked against the object with the
471new value as an argument.
8146585e 472
71db76ce 473If you set this to just C<1>, it generates a trigger which calls the
474C<_trigger_${attr_name}> method on C<$self>. This feature comes from
475L<MooseX::AttributeShortcuts>.
476
2e575bcd 477Note that Moose also passes the old value, if any; this feature is not yet
478supported.
479
8146585e 480L<Sub::Quote aware|/SUB QUOTE AWARE>
481
482=item * default
483
2e575bcd 484Takes a coderef which will get called with $self as its only argument
485to populate an attribute if no value is supplied to the constructor - or
486if the attribute is lazy, when the attribute is first retrieved if no
487value has yet been provided.
488
489Note that if your default is fired during new() there is no guarantee that
490other attributes have been populated yet so you should not rely on their
491existence.
8146585e 492
493L<Sub::Quote aware|/SUB QUOTE AWARE>
494
495=item * predicate
496
2e575bcd 497Takes a method name which will return true if an attribute has a value.
8146585e 498
71db76ce 499If you set this to just C<1>, the predicate is automatically named
500C<has_${attr_name}> if your attribute's name does not start with an
501underscore, or <_has_${attr_name_without_the_underscore}> if it does.
502This feature comes from L<MooseX::AttributeShortcuts>.
8146585e 503
504=item * builder
505
2e575bcd 506Takes a method name which will be called to create the attribute - functions
507exactly like default except that instead of calling
508
509 $default->($self);
510
511Moo will call
512
513 $self->$builder;
8146585e 514
71db76ce 515If you set this to just C<1>, the predicate is automatically named
516C<_build_${attr_name}>. This feature comes from L<MooseX::AttributeShortcuts>.
517
8146585e 518=item * clearer
519
520Takes a method name which will clear the attribute.
521
71db76ce 522If you set this to just C<1>, the clearer is automatically named
523C<clear_${attr_name}> if your attribute's name does not start with an
524underscore, or <_clear_${attr_name_without_the_underscore}> if it does.
525This feature comes from L<MooseX::AttributeShortcuts>.
526
8146585e 527=item * lazy
528
529B<Boolean>. Set this if you want values for the attribute to be grabbed
530lazily. This is usually a good idea if you have a L</builder> which requires
531another attribute to be set.
532
533=item * required
534
535B<Boolean>. Set this if the attribute must be passed on instantiation.
536
1eba910c 537=item * reader
538
539The value of this attribute will be the name of the method to get the value of
540the attribute. If you like Java style methods, you might set this to
541C<get_foo>
542
543=item * writer
544
545The value of this attribute will be the name of the method to set the value of
546the attribute. If you like Java style methods, you might set this to
547C<set_foo>
548
8146585e 549=item * weak_ref
550
551B<Boolean>. Set this if you want the reference that the attribute contains to
552be weakened; use this when circular references are possible, which will cause
553leaks.
554
555=item * init_arg
556
557Takes the name of the key to look for at instantiation time of the object. A
558common use of this is to make an underscored attribute have a non-underscored
559initialization name. C<undef> means that passing the value in on instantiation
71db76ce 560is ignored.
8146585e 561
562=back
563
564=head2 before
565
566 before foo => sub { ... };
567
568See L<< Class::Method::Modifiers/before method(s) => sub { ... } >> for full
569documentation.
570
571=head2 around
572
573 around foo => sub { ... };
574
575See L<< Class::Method::Modifiers/around method(s) => sub { ... } >> for full
576documentation.
577
578=head2 after
579
580 after foo => sub { ... };
581
582See L<< Class::Method::Modifiers/after method(s) => sub { ... } >> for full
583documentation.
584
8146585e 585=head1 SUB QUOTE AWARE
586
587L<Sub::Quote/quote_sub> allows us to create coderefs that are "inlineable,"
588giving us a handy, XS-free speed boost. Any option that is L<Sub::Quote>
589aware can take advantage of this.
590
2e575bcd 591=head1 INCOMPATIBILITIES WITH MOOSE
8146585e 592
5902c1fc 593There is no built in type system. C<isa> is verified with a coderef, if you
8146585e 594need complex types, just make a library of coderefs, or better yet, functions
5902c1fc 595that return quoted subs. L<MooX::Types::MooseLike> provides a similar API
596to L<MooseX::Types::Moose> so that you can write
597
598 has days_to_live => (is => 'ro', isa => Int);
599
600and have it work with both; it is hoped that providing only subrefs as an
601API will encourage the use of other type systems as well, since it's
602probably the weakest part of Moose design-wise.
8146585e 603
2e575bcd 604C<initializer> is not supported in core since the author considers it to be a
f88623a1 605bad idea but may be supported by an extension in future. Meanwhile C<trigger> or
606C<coerce> are more likely to be able to fulfill your needs.
8146585e 607
608There is no meta object. If you need this level of complexity you wanted
2e575bcd 609L<Moose> - Moo succeeds at being small because it explicitly does not
f9755246 610provide a metaprotocol. However, if you load L<Moose>, then
611
612 Class::MOP::class_of($moo_class_or_role)
613
614will return an appropriate metaclass pre-populated by L<Moo>.
8146585e 615
13e41b70 616No support for C<super>, C<override>, C<inner>, or C<augment> - the author
617considers augment to be a bad idea, and override can be translated:
618
619 override foo => sub {
620 ...
621 super();
622 ...
623 };
624
625 around foo => sub {
626 my ($orig, $self) = (shift, shift);
627 ...
628 $self->$orig(@_);
629 ...
630 };
8146585e 631
f2eac33e 632The C<dump> method is not provided by default. The author suggests loading
c96a6326 633L<Devel::Dwarn> into C<main::> (via C<perl -MDevel::Dwarn ...> for example) and
634using C<$obj-E<gt>$::Dwarn()> instead.
635
8146585e 636L</default> only supports coderefs, because doing otherwise is usually a
637mistake anyway.
638
f9755246 639C<lazy_build> is not supported; you are instead encouraged to use the
640C<is => 'lazy'> option supported by L<Moo> and L<MooseX::AttributeShortcuts>.
8146585e 641
2e575bcd 642C<auto_deref> is not supported since the author considers it a bad idea.
8146585e 643
f9755246 644C<documentation> will show up in a L<Moose> metaclass created from your class
c4074652 645but is otherwise ignored. Then again, L<Moose> ignores it as well, so this
f9755246 646is arguably not an incompatibility.
40f3e3aa 647
c4074652 648Since C<coerce> does not require C<isa> to be defined but L<Moose> does
649require it, the metaclass inflation for coerce-alone is a trifle insane
650and if you attempt to subtype the result will almost certainly break.
651
69673ca7 652Handling of warnings: when you C<use Moo> we enable FATAL warnings. The nearest
653similar invocation for L<Moose> would be:
654
655 use Moose;
656 use warnings FATAL => "all";
657
658Additionally, L<Moo> supports a set of attribute option shortcuts intended to
659reduce common boilerplate. The set of shortcuts is the same as in the L<Moose>
239d4711 660module L<MooseX::AttributeShortcuts> as of its version 0.009+. So if you:
69673ca7 661
662 package MyClass;
663 use Moo;
664
665The nearest L<Moose> invocation would be:
666
667 package MyClass;
668
669 use Moose;
670 use warnings FATAL => "all";
671 use MooseX::AttributeShortcuts;
672
5902c1fc 673or, if you're inheriting from a non-Moose class,
674
675 package MyClass;
676
677 use Moose;
678 use MooseX::NonMoose;
679 use warnings FATAL => "all";
680 use MooseX::AttributeShortcuts;
681
682Finally, Moose requires you to call
683
684 __PACKAGE__->meta->make_immutable;
685
686at the end of your class to get an inlined (i.e. not horribly slow)
687constructor. Moo does it automatically the first time ->new is called
688on your class.
689
660f3db2 690=head1 SUPPORT
691
9836a6ee 692Users' IRC: #moose on irc.perl.org
693
694Development and contribution IRC: #web-simple on irc.perl.org
660f3db2 695
40f3e3aa 696=head1 AUTHOR
697
698mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
699
700=head1 CONTRIBUTORS
701
5da684a2 702dg - David Leadbeater (cpan:DGL) <dgl@dgl.cx>
703
704frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>
705
706hobbs - Andrew Rodland (cpan:ARODLAND) <arodland@cpan.org>
707
708jnap - John Napiorkowski (cpan:JJNAPIORK) <jjn1056@yahoo.com>
709
710ribasushi - Peter Rabbitson (cpan:RIBASUSHI) <ribasushi@cpan.org>
40f3e3aa 711
11f7a042 712chip - Chip Salzenberg (cpan:CHIPS) <chip@pobox.com>
713
a17be455 714ajgb - Alex J. G. Burzyński (cpan:AJGB) <ajgb@cpan.org>
715
7b8177f8 716doy - Jesse Luehrs (cpan:DOY) <doy at tozt dot net>
717
1fb2de92 718perigrin - Chris Prather (cpan:PERIGRIN) <chris@prather.org>
719
3202e039 720Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>
721
e355471c 722ilmari - Dagfinn Ilmari Mannsåker (cpan:ILMARI) <ilmari@ilmari.org>
723
40f3e3aa 724=head1 COPYRIGHT
725
a958e36d 726Copyright (c) 2010-2011 the Moo L</AUTHOR> and L</CONTRIBUTORS>
40f3e3aa 727as listed above.
728
729=head1 LICENSE
730
731This library is free software and may be distributed under the same terms
732as perl itself.
733
734=cut