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