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