die in Attribute::_process_options if the attr is required but there is no way to...
[gitmo/Moose.git] / lib / Moose / Meta / Attribute.pm
CommitLineData
c0e30cf5 1
2package Moose::Meta::Attribute;
3
4use strict;
5use warnings;
6
78cd1d3b 7use Scalar::Util 'blessed', 'weaken', 'reftype';
a15dff8d 8use Carp 'confess';
7dbbdcab 9use Sub::Name 'subname';
a909a4df 10use overload ();
a15dff8d 11
ccf49e80 12our $VERSION = '0.18';
d44714be 13our $AUTHORITY = 'cpan:STEVAN';
78cd1d3b 14
8ee73eeb 15use Moose::Meta::Method::Accessor;
a3c7e2fe 16use Moose::Util::TypeConstraints ();
bc1e29b5 17
c0e30cf5 18use base 'Class::MOP::Attribute';
19
452bac1b 20# options which are not directly used
21# but we store them for metadata purposes
98aae381 22__PACKAGE__->meta->add_attribute('isa' => (reader => '_isa_metadata'));
23__PACKAGE__->meta->add_attribute('does' => (reader => '_does_metadata'));
24__PACKAGE__->meta->add_attribute('is' => (reader => '_is_metadata'));
452bac1b 25
26# these are actual options for the attrs
1a563243 27__PACKAGE__->meta->add_attribute('required' => (reader => 'is_required' ));
28__PACKAGE__->meta->add_attribute('lazy' => (reader => 'is_lazy' ));
26fbace8 29__PACKAGE__->meta->add_attribute('lazy_build' => (reader => 'is_lazy_build' ));
1a563243 30__PACKAGE__->meta->add_attribute('coerce' => (reader => 'should_coerce' ));
31__PACKAGE__->meta->add_attribute('weak_ref' => (reader => 'is_weak_ref' ));
32__PACKAGE__->meta->add_attribute('auto_deref' => (reader => 'should_auto_deref'));
82168dbb 33__PACKAGE__->meta->add_attribute('type_constraint' => (
34 reader => 'type_constraint',
35 predicate => 'has_type_constraint',
36));
8c9d74e7 37__PACKAGE__->meta->add_attribute('trigger' => (
38 reader => 'trigger',
39 predicate => 'has_trigger',
40));
452bac1b 41__PACKAGE__->meta->add_attribute('handles' => (
42 reader => 'handles',
43 predicate => 'has_handles',
44));
ddbdc0cb 45__PACKAGE__->meta->add_attribute('documentation' => (
46 reader => 'documentation',
47 predicate => 'has_documentation',
48));
82168dbb 49
78cd1d3b 50sub new {
f3c4e20e 51 my ($class, $name, %options) = @_;
52 $class->_process_options($name, \%options);
53 return $class->SUPER::new($name, %options);
1d768fb1 54}
55
ce0e8d63 56sub clone_and_inherit_options {
57 my ($self, %options) = @_;
83cc9094 58 # you can change default, required, coerce, documentation and lazy
ce0e8d63 59 my %actual_options;
83cc9094 60 foreach my $legal_option (qw(default coerce required documentation lazy)) {
ce0e8d63 61 if (exists $options{$legal_option}) {
62 $actual_options{$legal_option} = $options{$legal_option};
63 delete $options{$legal_option};
64 }
65 }
26fbace8 66
83cc9094 67 # handles can only be added, not changed
68 if ($options{handles}) {
69 confess "You can only add the 'handles' option, you cannot change it"
70 if $self->has_handles;
71 $actual_options{handles} = $options{handles};
72 delete $options{handles};
73 }
26fbace8 74
75 # isa can be changed, but only if the
76 # new type is a subtype
ce0e8d63 77 if ($options{isa}) {
78 my $type_constraint;
8de73ff1 79 if (blessed($options{isa}) && $options{isa}->isa('Moose::Meta::TypeConstraint')) {
80 $type_constraint = $options{isa};
81 }
82 else {
83 $type_constraint = Moose::Util::TypeConstraints::find_or_create_type_constraint(
84 $options{isa}
85 );
86 (defined $type_constraint)
87 || confess "Could not find the type constraint '" . $options{isa} . "'";
88 }
89 # NOTE:
90 # check here to see if the new type
91 # is a subtype of the old one
92 ($type_constraint->is_subtype_of($self->type_constraint->name))
93 || confess "New type constraint setting must be a subtype of inherited one"
94 # iff we have a type constraint that is ...
95 if $self->has_type_constraint;
96 # then we use it :)
97 $actual_options{type_constraint} = $type_constraint;
ce0e8d63 98 delete $options{isa};
99 }
26fbace8 100 (scalar keys %options == 0)
ce0e8d63 101 || confess "Illegal inherited options => (" . (join ', ' => keys %options) . ")";
102 $self->clone(%actual_options);
1d768fb1 103}
104
105sub _process_options {
106 my ($class, $name, $options) = @_;
8de73ff1 107
f3c4e20e 108 if (exists $options->{is}) {
8de73ff1 109 if ($options->{is} eq 'ro') {
110 $options->{reader} ||= $name;
111 (!exists $options->{trigger})
112 || confess "Cannot have a trigger on a read-only attribute";
113 }
114 elsif ($options->{is} eq 'rw') {
115 $options->{accessor} = $name;
116 ((reftype($options->{trigger}) || '') eq 'CODE')
117 || confess "Trigger must be a CODE ref"
118 if exists $options->{trigger};
119 }
120 else {
121 confess "I do not understand this option (is => " . $options->{is} . ")"
122 }
f3c4e20e 123 }
8de73ff1 124
f3c4e20e 125 if (exists $options->{isa}) {
f3c4e20e 126 if (exists $options->{does}) {
127 if (eval { $options->{isa}->can('does') }) {
128 ($options->{isa}->does($options->{does}))
129 || confess "Cannot have an isa option and a does option if the isa does not do the does";
130 }
131 else {
132 confess "Cannot have an isa option which cannot ->does()";
26fbace8 133 }
26fbace8 134 }
8de73ff1 135
f3c4e20e 136 # allow for anon-subtypes here ...
137 if (blessed($options->{isa}) && $options->{isa}->isa('Moose::Meta::TypeConstraint')) {
8de73ff1 138 $options->{type_constraint} = $options->{isa};
139 }
140 else {
141 $options->{type_constraint} = Moose::Util::TypeConstraints::find_or_create_type_constraint(
142 $options->{isa} => {
f3c4e20e 143 parent => Moose::Util::TypeConstraints::find_type_constraint('Object'),
144 constraint => sub { $_[0]->isa($options->{isa}) }
26fbace8 145 }
8de73ff1 146 );
147 }
f3c4e20e 148 }
149 elsif (exists $options->{does}) {
150 # allow for anon-subtypes here ...
151 if (blessed($options->{does}) && $options->{does}->isa('Moose::Meta::TypeConstraint')) {
238b424d 152 $options->{type_constraint} = $options->{does};
8de73ff1 153 }
154 else {
155 $options->{type_constraint} = Moose::Util::TypeConstraints::find_or_create_type_constraint(
156 $options->{does} => {
f3c4e20e 157 parent => Moose::Util::TypeConstraints::find_type_constraint('Role'),
238b424d 158 constraint => sub {
159 Moose::Util::does_role($_[0], $options->{does})
160 }
26fbace8 161 }
8de73ff1 162 );
163 }
f3c4e20e 164 }
8de73ff1 165
f3c4e20e 166 if (exists $options->{coerce} && $options->{coerce}) {
167 (exists $options->{type_constraint})
168 || confess "You cannot have coercion without specifying a type constraint";
8de73ff1 169 confess "You cannot have a weak reference to a coerced value"
170 if $options->{weak_ref};
f3c4e20e 171 }
8de73ff1 172
f3c4e20e 173 if (exists $options->{auto_deref} && $options->{auto_deref}) {
174 (exists $options->{type_constraint})
175 || confess "You cannot auto-dereference without specifying a type constraint";
176 ($options->{type_constraint}->is_a_type_of('ArrayRef') ||
8de73ff1 177 $options->{type_constraint}->is_a_type_of('HashRef'))
f3c4e20e 178 || confess "You cannot auto-dereference anything other than a ArrayRef or HashRef";
179 }
8de73ff1 180
f3c4e20e 181 if (exists $options->{lazy_build} && $options->{lazy_build} == 1) {
182 confess("You can not use lazy_build and default for the same attribute")
8de73ff1 183 if exists $options->{default};
a6c84c69 184 $options->{lazy} = 1;
185 $options->{required} = 1;
186 $options->{builder} ||= "_build_${name}";
187 if ($name =~ /^_/) {
f3c4e20e 188 $options->{clearer} ||= "_clear${name}";
189 $options->{predicate} ||= "_has${name}";
a6c84c69 190 }
191 else {
f3c4e20e 192 $options->{clearer} ||= "clear_${name}";
193 $options->{predicate} ||= "has_${name}";
26fbace8 194 }
f3c4e20e 195 }
8de73ff1 196
f3c4e20e 197 if (exists $options->{lazy} && $options->{lazy}) {
9edba990 198 (exists $options->{default} || defined $options->{builder} )
f3c4e20e 199 || confess "You cannot have lazy attribute without specifying a default value for it";
200 }
26fbace8 201
9edba990 202 if ( $options->{required} && !( ( !exists $options->{init_arg} || defined $options->{init_arg} ) || exists $options->{default} || defined $options->{builder} ) ) {
203 confess "You cannot have a required attribute without a default, builder, or an init_arg";
204 }
205
78cd1d3b 206}
c0e30cf5 207
d500266f 208sub initialize_instance_slot {
ddd0ec20 209 my ($self, $meta_instance, $instance, $params) = @_;
d500266f 210 my $init_arg = $self->init_arg();
211 # try to fetch the init arg from the %params ...
ddd0ec20 212
26fbace8 213 my $val;
1ed0b94f 214 my $value_is_set;
625d571f 215 if ( defined($init_arg) and exists $params->{$init_arg}) {
d500266f 216 $val = $params->{$init_arg};
2c78d811 217 $value_is_set = 1;
d500266f 218 }
219 else {
220 # skip it if it's lazy
221 return if $self->is_lazy;
222 # and die if it's required and doesn't have a default value
26fbace8 223 confess "Attribute (" . $self->name . ") is required"
224 if $self->is_required && !$self->has_default && !$self->has_builder;
ddd0ec20 225
1ed0b94f 226 # if nothing was in the %params, we can use the
227 # attribute's default value (if it has one)
228 if ($self->has_default) {
229 $val = $self->default($instance);
230 $value_is_set = 1;
a6c84c69 231 }
232 elsif ($self->has_builder) {
233 if (my $builder = $instance->can($self->builder)){
1ed0b94f 234 $val = $instance->$builder;
235 $value_is_set = 1;
a6c84c69 236 }
237 else {
0b26305c 238 confess(blessed($instance)." does not support builder method '".$self->builder."' for attribute '" . $self->name . "'");
1ed0b94f 239 }
a0748c37 240 }
26fbace8 241 }
242
1ed0b94f 243 return unless $value_is_set;
244
245 if ($self->has_type_constraint) {
246 my $type_constraint = $self->type_constraint;
247 if ($self->should_coerce && $type_constraint->has_coercion) {
248 $val = $type_constraint->coerce($val);
d500266f 249 }
1ed0b94f 250 (defined($type_constraint->check($val)))
251 || confess "Attribute (" .
252 $self->name .
253 ") does not pass the type constraint (" .
254 $type_constraint->name .
255 ") with '" .
256 (defined $val
6361ccf5 257 ? overload::StrVal($val)
1ed0b94f 258 : 'undef') .
259 "'";
260 }
ddd0ec20 261
ac1ef2f9 262 $meta_instance->set_slot_value($instance, $self->name, $val);
26fbace8 263 $meta_instance->weaken_slot_value($instance, $self->name)
a6c84c69 264 if ref $val && $self->is_weak_ref;
d500266f 265}
266
d617b644 267## Slot management
9e93dd19 268
946289d1 269sub set_value {
270 my ($self, $instance, $value) = @_;
26fbace8 271
946289d1 272 my $attr_name = $self->name;
26fbace8 273
946289d1 274 if ($self->is_required) {
26fbace8 275 defined($value)
946289d1 276 || confess "Attribute ($attr_name) is required, so cannot be set to undef";
277 }
26fbace8 278
946289d1 279 if ($self->has_type_constraint) {
26fbace8 280
946289d1 281 my $type_constraint = $self->type_constraint;
26fbace8 282
946289d1 283 if ($self->should_coerce) {
26fbace8 284 $value = $type_constraint->coerce($value);
946289d1 285 }
42bc21a4 286 $type_constraint->_compiled_type_constraint->($value)
26fbace8 287 || confess "Attribute ($attr_name) does not pass the type constraint ("
288 . $type_constraint->name
289 . ") with "
290 . (defined($value)
6361ccf5 291 ? ("'" . overload::StrVal($value) . "'")
a909a4df 292 : "undef")
946289d1 293 if defined($value);
294 }
26fbace8 295
946289d1 296 my $meta_instance = Class::MOP::Class->initialize(blessed($instance))
297 ->get_meta_instance;
26fbace8 298
299 $meta_instance->set_slot_value($instance, $attr_name, $value);
300
946289d1 301 if (ref $value && $self->is_weak_ref) {
26fbace8 302 $meta_instance->weaken_slot_value($instance, $attr_name);
946289d1 303 }
26fbace8 304
946289d1 305 if ($self->has_trigger) {
306 $self->trigger->($instance, $value, $self);
307 }
308}
309
310sub get_value {
311 my ($self, $instance) = @_;
26fbace8 312
946289d1 313 if ($self->is_lazy) {
8de73ff1 314 unless ($self->has_value($instance)) {
315 if ($self->has_default) {
316 my $default = $self->default($instance);
317 $self->set_value($instance, $default);
318 }
319 if ( $self->has_builder ){
a6c84c69 320 if (my $builder = $instance->can($self->builder)){
8de73ff1 321 $self->set_value($instance, $instance->$builder);
a6c84c69 322 }
323 else {
324 confess(blessed($instance)
325 . " does not support builder method '"
326 . $self->builder
327 . "' for attribute '"
328 . $self->name
329 . "'");
26fbace8 330 }
a6c84c69 331 }
332 else {
8de73ff1 333 $self->set_value($instance, undef);
26fbace8 334 }
8de73ff1 335 }
946289d1 336 }
26fbace8 337
946289d1 338 if ($self->should_auto_deref) {
26fbace8 339
946289d1 340 my $type_constraint = $self->type_constraint;
341
342 if ($type_constraint->is_a_type_of('ArrayRef')) {
343 my $rv = $self->SUPER::get_value($instance);
344 return unless defined $rv;
345 return wantarray ? @{ $rv } : $rv;
26fbace8 346 }
946289d1 347 elsif ($type_constraint->is_a_type_of('HashRef')) {
348 my $rv = $self->SUPER::get_value($instance);
349 return unless defined $rv;
350 return wantarray ? %{ $rv } : $rv;
26fbace8 351 }
946289d1 352 else {
353 confess "Can not auto de-reference the type constraint '" . $type_constraint->name . "'";
354 }
26fbace8 355
946289d1 356 }
357 else {
26fbace8 358
946289d1 359 return $self->SUPER::get_value($instance);
26fbace8 360 }
946289d1 361}
a15dff8d 362
26fbace8 363## installing accessors
c0e30cf5 364
d617b644 365sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
d7f17ebb 366
452bac1b 367sub install_accessors {
368 my $self = shift;
26fbace8 369 $self->SUPER::install_accessors(@_);
370
452bac1b 371 if ($self->has_handles) {
26fbace8 372
452bac1b 373 # NOTE:
374 # Here we canonicalize the 'handles' option
26fbace8 375 # this will sort out any details and always
376 # return an hash of methods which we want
452bac1b 377 # to delagate to, see that method for details
378 my %handles = $self->_canonicalize_handles();
26fbace8 379
f3c4e20e 380 # find the accessor method for this attribute
381 my $accessor = $self->get_read_method_ref;
382 # then unpack it if we need too ...
383 $accessor = $accessor->body if blessed $accessor;
26fbace8 384
452bac1b 385 # install the delegation ...
386 my $associated_class = $self->associated_class;
387 foreach my $handle (keys %handles) {
388 my $method_to_call = $handles{$handle};
7dbbdcab 389 my $class_name = $associated_class->name;
390 my $name = "${class_name}::${handle}";
26fbace8 391
452bac1b 392 (!$associated_class->has_method($handle))
393 || confess "You cannot overwrite a locally defined method ($handle) with a delegation";
26fbace8 394
d022f632 395 # NOTE:
396 # handles is not allowed to delegate
26fbace8 397 # any of these methods, as they will
398 # override the ones in your class, which
d022f632 399 # is almost certainly not what you want.
4fe78472 400
401 # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something
402 #cluck("Not delegating method '$handle' because it is a core method") and
403 next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle);
26fbace8 404
452bac1b 405 if ((reftype($method_to_call) || '') eq 'CODE') {
7dbbdcab 406 $associated_class->add_method($handle => subname $name, $method_to_call);
452bac1b 407 }
408 else {
7dbbdcab 409 $associated_class->add_method($handle => subname $name, sub {
f3c4e20e 410 my $proxy = (shift)->$accessor();
cbe25729 411 @_ = ($proxy, @_);
ccf49e80 412 (defined $proxy)
413 || confess "Cannot delegate $handle to $method_to_call because " .
414 "the value of " . $self->name . " is not defined";
7dbbdcab 415 goto &{ $proxy->can($method_to_call) || return };
452bac1b 416 });
417 }
418 }
419 }
26fbace8 420
452bac1b 421 return;
422}
423
98aae381 424# private methods to help delegation ...
425
452bac1b 426sub _canonicalize_handles {
427 my $self = shift;
428 my $handles = $self->handles;
c84f324f 429 if (my $handle_type = ref($handles)) {
430 if ($handle_type eq 'HASH') {
431 return %{$handles};
432 }
433 elsif ($handle_type eq 'ARRAY') {
434 return map { $_ => $_ } @{$handles};
435 }
436 elsif ($handle_type eq 'Regexp') {
437 ($self->has_type_constraint)
438 || confess "Cannot delegate methods based on a RegExpr without a type constraint (isa)";
26fbace8 439 return map { ($_ => $_) }
c84f324f 440 grep { /$handles/ } $self->_get_delegate_method_list;
441 }
442 elsif ($handle_type eq 'CODE') {
443 return $handles->($self, $self->_find_delegate_metaclass);
444 }
445 else {
446 confess "Unable to canonicalize the 'handles' option with $handles";
447 }
452bac1b 448 }
449 else {
c84f324f 450 my $role_meta = eval { $handles->meta };
451 if ($@) {
26fbace8 452 confess "Unable to canonicalize the 'handles' option with $handles because : $@";
c84f324f 453 }
454
455 (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
456 || confess "Unable to canonicalize the 'handles' option with $handles because ->meta is not a Moose::Meta::Role";
26fbace8 457
c84f324f 458 return map { $_ => $_ } (
26fbace8 459 $role_meta->get_method_list,
c84f324f 460 $role_meta->get_required_method_list
461 );
452bac1b 462 }
463}
464
465sub _find_delegate_metaclass {
466 my $self = shift;
98aae381 467 if (my $class = $self->_isa_metadata) {
26fbace8 468 # if the class does have
452bac1b 469 # a meta method, use it
470 return $class->meta if $class->can('meta');
26fbace8 471 # otherwise we might be
452bac1b 472 # dealing with a non-Moose
26fbace8 473 # class, and need to make
452bac1b 474 # our own metaclass
475 return Moose::Meta::Class->initialize($class);
476 }
98aae381 477 elsif (my $role = $self->_does_metadata) {
26fbace8 478 # our role will always have
452bac1b 479 # a meta method
98aae381 480 return $role->meta;
452bac1b 481 }
482 else {
483 confess "Cannot find delegate metaclass for attribute " . $self->name;
484 }
485}
486
487sub _get_delegate_method_list {
488 my $self = shift;
489 my $meta = $self->_find_delegate_metaclass;
490 if ($meta->isa('Class::MOP::Class')) {
093b12c2 491 return map { $_->{name} } # NOTE: !never! delegate &meta
26fbace8 492 grep { $_->{class} ne 'Moose::Object' && $_->{name} ne 'meta' }
452bac1b 493 $meta->compute_all_applicable_methods;
494 }
495 elsif ($meta->isa('Moose::Meta::Role')) {
26fbace8 496 return $meta->get_method_list;
452bac1b 497 }
498 else {
499 confess "Unable to recognize the delegate metaclass '$meta'";
500 }
501}
502
c0e30cf5 5031;
504
505__END__
506
507=pod
508
509=head1 NAME
510
6ba6d68c 511Moose::Meta::Attribute - The Moose attribute metaclass
c0e30cf5 512
513=head1 DESCRIPTION
514
26fbace8 515This is a subclass of L<Class::MOP::Attribute> with Moose specific
516extensions.
6ba6d68c 517
26fbace8 518For the most part, the only time you will ever encounter an
519instance of this class is if you are doing some serious deep
520introspection. To really understand this class, you need to refer
6ba6d68c 521to the L<Class::MOP::Attribute> documentation.
e522431d 522
c0e30cf5 523=head1 METHODS
524
6ba6d68c 525=head2 Overridden methods
526
26fbace8 527These methods override methods in L<Class::MOP::Attribute> and add
528Moose specific features. You can safely assume though that they
6ba6d68c 529will behave just as L<Class::MOP::Attribute> does.
530
c0e30cf5 531=over 4
532
533=item B<new>
534
d500266f 535=item B<initialize_instance_slot>
536
452bac1b 537=item B<install_accessors>
538
39b3bc94 539=item B<accessor_metaclass>
540
946289d1 541=item B<get_value>
542
543=item B<set_value>
544
bcbaa845 545 eval { $point->meta->get_attribute('x')->set_value($point, 'fourty-two') };
546 if($@) {
547 print "Oops: $@\n";
548 }
549
550I<Attribute (x) does not pass the type constraint (Int) with 'fourty-two'>
551
552Before setting the value, a check is made on the type constraint of
553the attribute, if it has one, to see if the value passes it. If the
554value fails to pass, the set operation dies with a L<Carp/confess>.
555
556Any coercion to convert values is done before checking the type constraint.
557
558To check a value against a type constraint before setting it, fetch the
ec00fa75 559attribute instance using L<Class::MOP::Class/find_attribute_by_name>,
bcbaa845 560fetch the type_constraint from the attribute using L<Moose::Meta::Attribute/type_constraint>
561and call L<Moose::Meta::TypeConstraint/check>. See L<Moose::Cookbook::RecipeX>
562for an example.
563
a15dff8d 564=back
565
6ba6d68c 566=head2 Additional Moose features
567
26fbace8 568Moose attributes support type-constraint checking, weak reference
569creation and type coercion.
6ba6d68c 570
a15dff8d 571=over 4
572
9e93dd19 573=item B<clone_and_inherit_options>
574
26fbace8 575This is to support the C<has '+foo'> feature, it clones an attribute
576from a superclass and allows a very specific set of changes to be made
9e93dd19 577to the attribute.
578
a15dff8d 579=item B<has_type_constraint>
580
6ba6d68c 581Returns true if this meta-attribute has a type constraint.
582
a15dff8d 583=item B<type_constraint>
584
26fbace8 585A read-only accessor for this meta-attribute's type constraint. For
586more information on what you can do with this, see the documentation
6ba6d68c 587for L<Moose::Meta::TypeConstraint>.
a15dff8d 588
452bac1b 589=item B<has_handles>
590
591Returns true if this meta-attribute performs delegation.
592
593=item B<handles>
594
595This returns the value which was passed into the handles option.
596
6ba6d68c 597=item B<is_weak_ref>
a15dff8d 598
02a0fb52 599Returns true if this meta-attribute produces a weak reference.
4b598ea3 600
ca01a97b 601=item B<is_required>
602
02a0fb52 603Returns true if this meta-attribute is required to have a value.
ca01a97b 604
605=item B<is_lazy>
606
02a0fb52 607Returns true if this meta-attribute should be initialized lazily.
ca01a97b 608
26fbace8 609NOTE: lazy attributes, B<must> have a C<default> or C<builder> field set.
610
611=item B<is_lazy_build>
612
613Returns true if this meta-attribute should be initialized lazily through
614the builder generated by lazy_build. Using C<lazy_build =E<gt> 1> will
615make your attribute required and lazy. In addition it will set the builder, clearer
616and predicate options for you using the following convention.
617
618 #If your attribute name starts with an underscore:
619 has '_foo' => (lazy_build => 1);
620 #is the same as
58f85113 621 has '_foo' => (lazy => 1, required => 1, predicate => '_has_foo', clearer => '_clear_foo', builder => '_build__foo);
26fbace8 622 # or
58f85113 623 has '_foo' => (lazy => 1, required => 1, predicate => '_has_foo', clearer => '_clear_foo', default => sub{shift->_build__foo});
26fbace8 624
625 #If your attribute name does not start with an underscore:
58f85113 626 has 'foo' => (lazy_build => 1);
627 #is the same as
628 has 'foo' => (lazy => 1, required => 1, predicate => 'has_foo', clearer => 'clear_foo', builder => '_build_foo);
26fbace8 629 # or
58f85113 630 has 'foo' => (lazy => 1, required => 1, predicate => 'has_foo', clearer => 'clear_foo', default => sub{shift->_build_foo});
631
632The reason for the different naming of the C<builder> is that the C<builder>
633method is a private method while the C<clearer> and C<predicate> methods
634are public methods.
26fbace8 635
636NOTE: This means your class should provide a method whose name matches the value
58f85113 637of the builder part, in this case _build__foo or _build_foo.
ca01a97b 638
34a66aa3 639=item B<should_coerce>
4b598ea3 640
02a0fb52 641Returns true if this meta-attribute should perform type coercion.
6ba6d68c 642
536f0b17 643=item B<should_auto_deref>
644
26fbace8 645Returns true if this meta-attribute should perform automatic
646auto-dereferencing.
536f0b17 647
26fbace8 648NOTE: This can only be done for attributes whose type constraint is
536f0b17 649either I<ArrayRef> or I<HashRef>.
650
8c9d74e7 651=item B<has_trigger>
652
02a0fb52 653Returns true if this meta-attribute has a trigger set.
654
8c9d74e7 655=item B<trigger>
656
26fbace8 657This is a CODE reference which will be executed every time the
658value of an attribute is assigned. The CODE ref will get two values,
659the invocant and the new value. This can be used to handle I<basic>
02a0fb52 660bi-directional relations.
661
ddbdc0cb 662=item B<documentation>
663
26fbace8 664This is a string which contains the documentation for this attribute.
ddbdc0cb 665It serves no direct purpose right now, but it might in the future
666in some kind of automated documentation system perhaps.
667
668=item B<has_documentation>
669
670Returns true if this meta-attribute has any documentation.
671
c0e30cf5 672=back
673
674=head1 BUGS
675
26fbace8 676All complex software has bugs lurking in it, and this module is no
c0e30cf5 677exception. If you find a bug please either email me, or add the bug
678to cpan-RT.
679
c0e30cf5 680=head1 AUTHOR
681
682Stevan Little E<lt>stevan@iinteractive.comE<gt>
683
98aae381 684Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
685
c0e30cf5 686=head1 COPYRIGHT AND LICENSE
687
778db3ac 688Copyright 2006-2008 by Infinity Interactive, Inc.
c0e30cf5 689
690L<http://www.iinteractive.com>
691
692This library is free software; you can redistribute it and/or modify
26fbace8 693it under the same terms as Perl itself.
c0e30cf5 694
8a7a9c53 695=cut