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