making has $name => {} fail
[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)))
688fcdda 251 || confess "Attribute ("
252 . $self->name
253 . ") does not pass the type constraint because: "
254 . $type_constraint->get_message($val);
1ed0b94f 255 }
ddd0ec20 256
ac1ef2f9 257 $meta_instance->set_slot_value($instance, $self->name, $val);
26fbace8 258 $meta_instance->weaken_slot_value($instance, $self->name)
a6c84c69 259 if ref $val && $self->is_weak_ref;
d500266f 260}
261
d617b644 262## Slot management
9e93dd19 263
946289d1 264sub set_value {
265 my ($self, $instance, $value) = @_;
26fbace8 266
946289d1 267 my $attr_name = $self->name;
26fbace8 268
946289d1 269 if ($self->is_required) {
26fbace8 270 defined($value)
946289d1 271 || confess "Attribute ($attr_name) is required, so cannot be set to undef";
272 }
26fbace8 273
946289d1 274 if ($self->has_type_constraint) {
26fbace8 275
946289d1 276 my $type_constraint = $self->type_constraint;
26fbace8 277
946289d1 278 if ($self->should_coerce) {
26fbace8 279 $value = $type_constraint->coerce($value);
688fcdda 280 }
42bc21a4 281 $type_constraint->_compiled_type_constraint->($value)
688fcdda 282 || confess "Attribute ("
283 . $self->name
284 . ") does not pass the type constraint because "
285 . $type_constraint->get_message($value)
286 if defined($value);
946289d1 287 }
26fbace8 288
946289d1 289 my $meta_instance = Class::MOP::Class->initialize(blessed($instance))
290 ->get_meta_instance;
26fbace8 291
292 $meta_instance->set_slot_value($instance, $attr_name, $value);
293
946289d1 294 if (ref $value && $self->is_weak_ref) {
26fbace8 295 $meta_instance->weaken_slot_value($instance, $attr_name);
946289d1 296 }
26fbace8 297
946289d1 298 if ($self->has_trigger) {
299 $self->trigger->($instance, $value, $self);
300 }
301}
302
303sub get_value {
304 my ($self, $instance) = @_;
26fbace8 305
946289d1 306 if ($self->is_lazy) {
8de73ff1 307 unless ($self->has_value($instance)) {
308 if ($self->has_default) {
309 my $default = $self->default($instance);
310 $self->set_value($instance, $default);
311 }
312 if ( $self->has_builder ){
a6c84c69 313 if (my $builder = $instance->can($self->builder)){
8de73ff1 314 $self->set_value($instance, $instance->$builder);
a6c84c69 315 }
316 else {
317 confess(blessed($instance)
318 . " does not support builder method '"
319 . $self->builder
320 . "' for attribute '"
321 . $self->name
322 . "'");
26fbace8 323 }
a6c84c69 324 }
325 else {
8de73ff1 326 $self->set_value($instance, undef);
26fbace8 327 }
8de73ff1 328 }
946289d1 329 }
26fbace8 330
946289d1 331 if ($self->should_auto_deref) {
26fbace8 332
946289d1 333 my $type_constraint = $self->type_constraint;
334
335 if ($type_constraint->is_a_type_of('ArrayRef')) {
336 my $rv = $self->SUPER::get_value($instance);
337 return unless defined $rv;
338 return wantarray ? @{ $rv } : $rv;
26fbace8 339 }
946289d1 340 elsif ($type_constraint->is_a_type_of('HashRef')) {
341 my $rv = $self->SUPER::get_value($instance);
342 return unless defined $rv;
343 return wantarray ? %{ $rv } : $rv;
26fbace8 344 }
946289d1 345 else {
346 confess "Can not auto de-reference the type constraint '" . $type_constraint->name . "'";
347 }
26fbace8 348
946289d1 349 }
350 else {
26fbace8 351
946289d1 352 return $self->SUPER::get_value($instance);
26fbace8 353 }
946289d1 354}
a15dff8d 355
26fbace8 356## installing accessors
c0e30cf5 357
d617b644 358sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
d7f17ebb 359
452bac1b 360sub install_accessors {
361 my $self = shift;
26fbace8 362 $self->SUPER::install_accessors(@_);
363
452bac1b 364 if ($self->has_handles) {
26fbace8 365
452bac1b 366 # NOTE:
367 # Here we canonicalize the 'handles' option
26fbace8 368 # this will sort out any details and always
369 # return an hash of methods which we want
452bac1b 370 # to delagate to, see that method for details
371 my %handles = $self->_canonicalize_handles();
26fbace8 372
f3c4e20e 373 # find the accessor method for this attribute
374 my $accessor = $self->get_read_method_ref;
375 # then unpack it if we need too ...
376 $accessor = $accessor->body if blessed $accessor;
26fbace8 377
452bac1b 378 # install the delegation ...
379 my $associated_class = $self->associated_class;
380 foreach my $handle (keys %handles) {
381 my $method_to_call = $handles{$handle};
7dbbdcab 382 my $class_name = $associated_class->name;
383 my $name = "${class_name}::${handle}";
26fbace8 384
452bac1b 385 (!$associated_class->has_method($handle))
386 || confess "You cannot overwrite a locally defined method ($handle) with a delegation";
26fbace8 387
d022f632 388 # NOTE:
389 # handles is not allowed to delegate
26fbace8 390 # any of these methods, as they will
391 # override the ones in your class, which
d022f632 392 # is almost certainly not what you want.
4fe78472 393
394 # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something
395 #cluck("Not delegating method '$handle' because it is a core method") and
396 next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle);
26fbace8 397
452bac1b 398 if ((reftype($method_to_call) || '') eq 'CODE') {
7dbbdcab 399 $associated_class->add_method($handle => subname $name, $method_to_call);
452bac1b 400 }
401 else {
7dbbdcab 402 $associated_class->add_method($handle => subname $name, sub {
f3c4e20e 403 my $proxy = (shift)->$accessor();
cbe25729 404 @_ = ($proxy, @_);
ccf49e80 405 (defined $proxy)
406 || confess "Cannot delegate $handle to $method_to_call because " .
407 "the value of " . $self->name . " is not defined";
7dbbdcab 408 goto &{ $proxy->can($method_to_call) || return };
452bac1b 409 });
410 }
411 }
412 }
26fbace8 413
452bac1b 414 return;
415}
416
98aae381 417# private methods to help delegation ...
418
452bac1b 419sub _canonicalize_handles {
420 my $self = shift;
421 my $handles = $self->handles;
c84f324f 422 if (my $handle_type = ref($handles)) {
423 if ($handle_type eq 'HASH') {
424 return %{$handles};
425 }
426 elsif ($handle_type eq 'ARRAY') {
427 return map { $_ => $_ } @{$handles};
428 }
429 elsif ($handle_type eq 'Regexp') {
430 ($self->has_type_constraint)
431 || confess "Cannot delegate methods based on a RegExpr without a type constraint (isa)";
26fbace8 432 return map { ($_ => $_) }
c84f324f 433 grep { /$handles/ } $self->_get_delegate_method_list;
434 }
435 elsif ($handle_type eq 'CODE') {
436 return $handles->($self, $self->_find_delegate_metaclass);
437 }
438 else {
439 confess "Unable to canonicalize the 'handles' option with $handles";
440 }
452bac1b 441 }
442 else {
c84f324f 443 my $role_meta = eval { $handles->meta };
444 if ($@) {
26fbace8 445 confess "Unable to canonicalize the 'handles' option with $handles because : $@";
c84f324f 446 }
447
448 (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
449 || confess "Unable to canonicalize the 'handles' option with $handles because ->meta is not a Moose::Meta::Role";
26fbace8 450
c84f324f 451 return map { $_ => $_ } (
26fbace8 452 $role_meta->get_method_list,
c84f324f 453 $role_meta->get_required_method_list
454 );
452bac1b 455 }
456}
457
458sub _find_delegate_metaclass {
459 my $self = shift;
98aae381 460 if (my $class = $self->_isa_metadata) {
26fbace8 461 # if the class does have
452bac1b 462 # a meta method, use it
463 return $class->meta if $class->can('meta');
26fbace8 464 # otherwise we might be
452bac1b 465 # dealing with a non-Moose
26fbace8 466 # class, and need to make
452bac1b 467 # our own metaclass
468 return Moose::Meta::Class->initialize($class);
469 }
98aae381 470 elsif (my $role = $self->_does_metadata) {
26fbace8 471 # our role will always have
452bac1b 472 # a meta method
98aae381 473 return $role->meta;
452bac1b 474 }
475 else {
476 confess "Cannot find delegate metaclass for attribute " . $self->name;
477 }
478}
479
480sub _get_delegate_method_list {
481 my $self = shift;
482 my $meta = $self->_find_delegate_metaclass;
483 if ($meta->isa('Class::MOP::Class')) {
093b12c2 484 return map { $_->{name} } # NOTE: !never! delegate &meta
26fbace8 485 grep { $_->{class} ne 'Moose::Object' && $_->{name} ne 'meta' }
452bac1b 486 $meta->compute_all_applicable_methods;
487 }
488 elsif ($meta->isa('Moose::Meta::Role')) {
26fbace8 489 return $meta->get_method_list;
452bac1b 490 }
491 else {
492 confess "Unable to recognize the delegate metaclass '$meta'";
493 }
494}
495
c0e30cf5 4961;
497
498__END__
499
500=pod
501
502=head1 NAME
503
6ba6d68c 504Moose::Meta::Attribute - The Moose attribute metaclass
c0e30cf5 505
506=head1 DESCRIPTION
507
26fbace8 508This is a subclass of L<Class::MOP::Attribute> with Moose specific
509extensions.
6ba6d68c 510
26fbace8 511For the most part, the only time you will ever encounter an
512instance of this class is if you are doing some serious deep
513introspection. To really understand this class, you need to refer
6ba6d68c 514to the L<Class::MOP::Attribute> documentation.
e522431d 515
c0e30cf5 516=head1 METHODS
517
6ba6d68c 518=head2 Overridden methods
519
26fbace8 520These methods override methods in L<Class::MOP::Attribute> and add
521Moose specific features. You can safely assume though that they
6ba6d68c 522will behave just as L<Class::MOP::Attribute> does.
523
c0e30cf5 524=over 4
525
526=item B<new>
527
d500266f 528=item B<initialize_instance_slot>
529
452bac1b 530=item B<install_accessors>
531
39b3bc94 532=item B<accessor_metaclass>
533
946289d1 534=item B<get_value>
535
536=item B<set_value>
537
bcbaa845 538 eval { $point->meta->get_attribute('x')->set_value($point, 'fourty-two') };
539 if($@) {
540 print "Oops: $@\n";
541 }
542
543I<Attribute (x) does not pass the type constraint (Int) with 'fourty-two'>
544
545Before setting the value, a check is made on the type constraint of
546the attribute, if it has one, to see if the value passes it. If the
547value fails to pass, the set operation dies with a L<Carp/confess>.
548
549Any coercion to convert values is done before checking the type constraint.
550
551To check a value against a type constraint before setting it, fetch the
ec00fa75 552attribute instance using L<Class::MOP::Class/find_attribute_by_name>,
bcbaa845 553fetch the type_constraint from the attribute using L<Moose::Meta::Attribute/type_constraint>
554and call L<Moose::Meta::TypeConstraint/check>. See L<Moose::Cookbook::RecipeX>
555for an example.
556
a15dff8d 557=back
558
6ba6d68c 559=head2 Additional Moose features
560
26fbace8 561Moose attributes support type-constraint checking, weak reference
562creation and type coercion.
6ba6d68c 563
a15dff8d 564=over 4
565
9e93dd19 566=item B<clone_and_inherit_options>
567
26fbace8 568This is to support the C<has '+foo'> feature, it clones an attribute
569from a superclass and allows a very specific set of changes to be made
9e93dd19 570to the attribute.
571
a15dff8d 572=item B<has_type_constraint>
573
6ba6d68c 574Returns true if this meta-attribute has a type constraint.
575
a15dff8d 576=item B<type_constraint>
577
26fbace8 578A read-only accessor for this meta-attribute's type constraint. For
579more information on what you can do with this, see the documentation
6ba6d68c 580for L<Moose::Meta::TypeConstraint>.
a15dff8d 581
452bac1b 582=item B<has_handles>
583
584Returns true if this meta-attribute performs delegation.
585
586=item B<handles>
587
588This returns the value which was passed into the handles option.
589
6ba6d68c 590=item B<is_weak_ref>
a15dff8d 591
02a0fb52 592Returns true if this meta-attribute produces a weak reference.
4b598ea3 593
ca01a97b 594=item B<is_required>
595
02a0fb52 596Returns true if this meta-attribute is required to have a value.
ca01a97b 597
598=item B<is_lazy>
599
02a0fb52 600Returns true if this meta-attribute should be initialized lazily.
ca01a97b 601
26fbace8 602NOTE: lazy attributes, B<must> have a C<default> or C<builder> field set.
603
604=item B<is_lazy_build>
605
606Returns true if this meta-attribute should be initialized lazily through
607the builder generated by lazy_build. Using C<lazy_build =E<gt> 1> will
608make your attribute required and lazy. In addition it will set the builder, clearer
609and predicate options for you using the following convention.
610
611 #If your attribute name starts with an underscore:
612 has '_foo' => (lazy_build => 1);
613 #is the same as
58f85113 614 has '_foo' => (lazy => 1, required => 1, predicate => '_has_foo', clearer => '_clear_foo', builder => '_build__foo);
26fbace8 615 # or
58f85113 616 has '_foo' => (lazy => 1, required => 1, predicate => '_has_foo', clearer => '_clear_foo', default => sub{shift->_build__foo});
26fbace8 617
618 #If your attribute name does not start with an underscore:
58f85113 619 has 'foo' => (lazy_build => 1);
620 #is the same as
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});
624
625The reason for the different naming of the C<builder> is that the C<builder>
626method is a private method while the C<clearer> and C<predicate> methods
627are public methods.
26fbace8 628
629NOTE: This means your class should provide a method whose name matches the value
58f85113 630of the builder part, in this case _build__foo or _build_foo.
ca01a97b 631
34a66aa3 632=item B<should_coerce>
4b598ea3 633
02a0fb52 634Returns true if this meta-attribute should perform type coercion.
6ba6d68c 635
536f0b17 636=item B<should_auto_deref>
637
26fbace8 638Returns true if this meta-attribute should perform automatic
639auto-dereferencing.
536f0b17 640
26fbace8 641NOTE: This can only be done for attributes whose type constraint is
536f0b17 642either I<ArrayRef> or I<HashRef>.
643
8c9d74e7 644=item B<has_trigger>
645
02a0fb52 646Returns true if this meta-attribute has a trigger set.
647
8c9d74e7 648=item B<trigger>
649
26fbace8 650This is a CODE reference which will be executed every time the
651value of an attribute is assigned. The CODE ref will get two values,
652the invocant and the new value. This can be used to handle I<basic>
02a0fb52 653bi-directional relations.
654
ddbdc0cb 655=item B<documentation>
656
26fbace8 657This is a string which contains the documentation for this attribute.
ddbdc0cb 658It serves no direct purpose right now, but it might in the future
659in some kind of automated documentation system perhaps.
660
661=item B<has_documentation>
662
663Returns true if this meta-attribute has any documentation.
664
c0e30cf5 665=back
666
667=head1 BUGS
668
26fbace8 669All complex software has bugs lurking in it, and this module is no
c0e30cf5 670exception. If you find a bug please either email me, or add the bug
671to cpan-RT.
672
c0e30cf5 673=head1 AUTHOR
674
675Stevan Little E<lt>stevan@iinteractive.comE<gt>
676
98aae381 677Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
678
c0e30cf5 679=head1 COPYRIGHT AND LICENSE
680
778db3ac 681Copyright 2006-2008 by Infinity Interactive, Inc.
c0e30cf5 682
683L<http://www.iinteractive.com>
684
685This library is free software; you can redistribute it and/or modify
26fbace8 686it under the same terms as Perl itself.
c0e30cf5 687
8a7a9c53 688=cut