X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FMeta%2FAttribute.pm;h=a0d2469f9bb7834ea90f7e18303f56e8fc1e10ce;hb=ac0ece3dc42ae7e0402a46eb25dbdc57f6cbcc9b;hp=b9bcb6d0f8672644334c6fe7fa33295bd7d01ead;hpb=39b3bc94309529721acb365c64b2ff52a0c2be35;p=gitmo%2FMoose.git diff --git a/lib/Moose/Meta/Attribute.pm b/lib/Moose/Meta/Attribute.pm index b9bcb6d..a0d2469 100644 --- a/lib/Moose/Meta/Attribute.pm +++ b/lib/Moose/Meta/Attribute.pm @@ -7,7 +7,8 @@ use warnings; use Scalar::Util 'blessed', 'weaken', 'reftype'; use Carp 'confess'; -our $VERSION = '0.08'; +our $VERSION = '0.10'; +our $AUTHORITY = 'cpan:STEVAN'; use Moose::Meta::Method::Accessor; use Moose::Util::TypeConstraints (); @@ -38,6 +39,10 @@ __PACKAGE__->meta->add_attribute('handles' => ( reader => 'handles', predicate => 'has_handles', )); +__PACKAGE__->meta->add_attribute('documentation' => ( + reader => 'documentation', + predicate => 'has_documentation', +)); sub new { my ($class, $name, %options) = @_; @@ -47,9 +52,9 @@ sub new { sub clone_and_inherit_options { my ($self, %options) = @_; - # you can change default, required and coerce + # you can change default, required, coerce and documentation my %actual_options; - foreach my $legal_option (qw(default coerce required)) { + foreach my $legal_option (qw(default coerce required documentation)) { if (exists $options{$legal_option}) { $actual_options{$legal_option} = $options{$legal_option}; delete $options{$legal_option}; @@ -229,21 +234,82 @@ sub initialize_instance_slot { ## Slot management -#sub set_value { -# my ($self, $instance, $value) = @_; -#} -# -#sub get_value { -# my ($self, $instance) = @_; -#} -# -#sub has_value { -# my ($self, $instance) = @_; -#} -# -#sub clear_value { -# my ($self, $instance) = @_; -#} +sub set_value { + my ($self, $instance, $value) = @_; + + my $attr_name = $self->name; + + if ($self->is_required) { + defined($value) + || confess "Attribute ($attr_name) is required, so cannot be set to undef"; + } + + if ($self->has_type_constraint) { + + my $type_constraint = $self->type_constraint; + + if ($self->should_coerce) { + $value = $type_constraint->coerce($value); + } + defined($type_constraint->_compiled_type_constraint->($value)) + || confess "Attribute ($attr_name) does not pass the type constraint (" + . $type_constraint->name . ") with " . (defined($value) ? ("'" . $value . "'") : "undef") + if defined($value); + } + + my $meta_instance = Class::MOP::Class->initialize(blessed($instance)) + ->get_meta_instance; + + $meta_instance->set_slot_value($instance, $attr_name, $value); + + if (ref $value && $self->is_weak_ref) { + $meta_instance->weaken_slot_value($instance, $attr_name); + } + + if ($self->has_trigger) { + $self->trigger->($instance, $value, $self); + } +} + +sub get_value { + my ($self, $instance) = @_; + + if ($self->is_lazy) { + unless ($self->has_value($instance)) { + if ($self->has_default) { + my $default = $self->default($instance); + $self->set_value($instance, $default); + } + else { + $self->set_value($instance, undef); + } + } + } + + if ($self->should_auto_deref) { + + my $type_constraint = $self->type_constraint; + + if ($type_constraint->is_a_type_of('ArrayRef')) { + my $rv = $self->SUPER::get_value($instance); + return unless defined $rv; + return wantarray ? @{ $rv } : $rv; + } + elsif ($type_constraint->is_a_type_of('HashRef')) { + my $rv = $self->SUPER::get_value($instance); + return unless defined $rv; + return wantarray ? %{ $rv } : $rv; + } + else { + confess "Can not auto de-reference the type constraint '" . $type_constraint->name . "'"; + } + + } + else { + + return $self->SUPER::get_value($instance); + } +} ## installing accessors @@ -279,6 +345,13 @@ sub install_accessors { (!$associated_class->has_method($handle)) || confess "You cannot overwrite a locally defined method ($handle) with a delegation"; + # NOTE: + # handles is not allowed to delegate + # any of these methods, as they will + # override the ones in your class, which + # is almost certainly not what you want. + next if $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle); + if ((reftype($method_to_call) || '') eq 'CODE') { $associated_class->add_method($handle => $method_to_call); } @@ -312,7 +385,7 @@ sub _canonicalize_handles { ($self->has_type_constraint) || confess "Cannot delegate methods based on a RegExpr without a type constraint (isa)"; return map { ($_ => $_) } - grep { $handles } $self->_get_delegate_method_list; + grep { /$handles/ } $self->_get_delegate_method_list; } elsif (ref($handles) eq 'CODE') { return $handles->($self, $self->_find_delegate_metaclass); @@ -398,6 +471,10 @@ will behave just as L does. =item B +=item B + +=item B + =back =head2 Additional Moose features @@ -468,6 +545,16 @@ value of an attribute is assigned. The CODE ref will get two values, the invocant and the new value. This can be used to handle I bi-directional relations. +=item B + +This is a string which contains the documentation for this attribute. +It serves no direct purpose right now, but it might in the future +in some kind of automated documentation system perhaps. + +=item B + +Returns true if this meta-attribute has any documentation. + =back =head1 BUGS @@ -484,7 +571,7 @@ Yuval Kogman Enothingmuch@woobling.comE =head1 COPYRIGHT AND LICENSE -Copyright 2006 by Infinity Interactive, Inc. +Copyright 2006, 2007 by Infinity Interactive, Inc. L