add curried_arguments, usable from hashref handles
[gitmo/Moose.git] / lib / Moose / Meta / Attribute.pm
index 54ba639..bf599be 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Scalar::Util 'blessed', 'weaken';
 use overload     ();
 
-our $VERSION   = '0.79';
+our $VERSION   = '0.83';
 our $AUTHORITY = 'cpan:STEVAN';
 
 use Moose::Meta::Method::Accessor;
@@ -290,6 +290,9 @@ sub _process_options {
                 $options->{accessor} ||= $name;
             }
         }
+        elsif ($options->{is} eq 'bare') {
+            # do nothing, but don't complain (later) about missing methods
+        }
         else {
             $class->throw_error("I do not understand this option (is => " . $options->{is} . ") on attribute ($name)", data => $options->{is});
         }
@@ -537,6 +540,16 @@ sub install_accessors {
     my $self = shift;
     $self->SUPER::install_accessors(@_);
     $self->install_delegation if $self->has_handles;
+    unless (
+        @{ $self->associated_methods }
+        || ($self->_is_metadata || '') eq 'bare'
+    ) {
+        Carp::cluck(
+            'Attribute (' . $self->name . ') has no associated methods'
+            . ' (did you mean to provide an "is" argument?)'
+            . "\n"
+        )
+    }
     return;
 }
 
@@ -581,6 +594,7 @@ sub install_delegation {
         my $method = $self->_make_delegation_method($handle, $method_to_call);
 
         $self->associated_class->add_method($method->name, $method);
+        $self->associate_method($method);
     }
 }
 
@@ -614,6 +628,9 @@ sub _canonicalize_handles {
         elsif ($handle_type eq 'CODE') {
             return $handles->($self, $self->_find_delegate_metaclass);
         }
+        elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::DuckType')) {
+            return map { $_ => $_ } @{ $handles->methods };
+        }
         else {
             $self->throw_error("Unable to canonicalize the 'handles' option with $handles", data => $handles);
         }
@@ -627,7 +644,7 @@ sub _canonicalize_handles {
 
         return map { $_ => $_ } (
             $role_meta->get_method_list,
-            $role_meta->get_required_method_list
+            map { $_->name } $role_meta->get_required_method_list,
         );
     }
 }
@@ -674,11 +691,17 @@ sub _make_delegation_method {
     $method_body = $method_to_call
         if 'CODE' eq ref($method_to_call);
 
+    my $curried_arguments = [];
+
+    ($method_to_call, $curried_arguments) = @$method_to_call
+        if 'ARRAY' eq ref($method_to_call);
+
     return $self->delegation_metaclass->new(
         name               => $handle_name,
         package_name       => $self->associated_class->name,
         attribute          => $self,
         delegate_to_method => $method_to_call,
+        curried_arguments  => $curried_arguments,
     );
 }
 
@@ -761,7 +784,7 @@ It adds the following options to the constructor:
 
 =over 8
 
-=item * is => 'ro' or 'rw'
+=item * is => 'ro', 'rw', 'bare'
 
 This provides a shorthand for specifying the C<reader>, C<writer>, or
 C<accessor> names. If the attribute is read-only ('ro') then it will
@@ -772,6 +795,11 @@ with the same name. If you provide an explicit C<writer> for a
 read-write attribute, then you will have a C<reader> with the same
 name as the attribute, and a C<writer> with the name you provided.
 
+Use 'bare' when you are deliberately not installing any methods
+(accessor, reader, etc.) associated with this attribute; otherwise,
+Moose will issue a deprecation warning when this attribute is added to a
+metaclass.
+
 =item * isa => $type
 
 This option accepts a type. The type can be a string, which should be
@@ -910,6 +938,11 @@ for an example.
 
 This method overrides the parent to also install delegation methods.
 
+If, after installing all methods, the attribute object has no associated
+methods, it throws an error unless C<< is => 'bare' >> was passed to the
+attribute constructor.  (Trying to add an attribute that has no associated
+methods is almost always an error.)
+
 =item B<< $attr->remove_accessors >>
 
 This method overrides the parent to also remove delegation methods.