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