has +name from role officially supported
Stevan Little [Sun, 24 Feb 2008 20:03:20 +0000 (20:03 +0000)]
Changes
lib/Moose.pm
lib/Moose/Meta/Attribute.pm
t/030_roles/017_extending_role_attrs.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index fb9fba6..a14b044 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,16 @@
 Revision history for Perl extension Moose
 
 0.39
+    * Moose
+      - documenting the use of '+name' with attributes 
+        that come from recently composed roles. It makes
+        sense, people are using it, and so why not just 
+        officially support it.
+    
+    * t/
+      - making test for using '+name' on attributes consumed 
+        from a role, it works and makes sense too.    
+
     * Moose::Meta::Attribute 
       - fix handles so that it doesn't return nothing 
         when the method cannot be found, not sure why 
index 6c48b60..4e471dd 100644 (file)
@@ -601,7 +601,8 @@ a HASH ref) of the methods you want mapped.
 =item B<has +$name =E<gt> %options>
 
 This is variation on the normal attibute creator C<has> which allows you to
-clone and extend an attribute from a superclass. Here is a quick example:
+clone and extend an attribute from a superclass or from a role. Here is an 
+example of the superclass usage:
 
   package Foo;
   use Moose;
@@ -623,6 +624,27 @@ What is happening here is that B<My::Foo> is cloning the C<message> attribute
 from its parent class B<Foo>, retaining the C<is =E<gt> 'rw'> and C<isa =E<gt>
 'Str'> characteristics, but changing the value in C<default>.
 
+Here is another example, but within the context of a role:
+
+  package Foo::Role;
+  use Moose::Role;
+  
+  has 'message' => (
+      is      => 'rw',
+      isa     => 'Str',
+      default => 'Hello, I am a Foo'
+  );
+  
+  package My::Foo;
+  use Moose;
+  
+  with 'Foo::Role';
+  
+  has '+message' => (default => 'Hello I am My::Foo');
+
+In this case, we are basically taking the attribute which the role supplied 
+and altering it within the bounds of this feature.
+
 This feature is restricted somewhat, so as to try and force at least I<some>
 sanity into it. You are only allowed to change the following attributes:
 
@@ -658,6 +680,11 @@ subtype of the old type.
 You are allowed to B<add> a new C<handles> definition, but you are B<not>
 allowed to I<change> one.
 
+=item I<builder>
+
+You are allowed to B<add> a new C<builder> definition, but you are B<not>
+allowed to I<change> one.
+
 =back
 
 =item B<before $name|@names =E<gt> sub { ... }>
index b7436cc..80c16cd 100644 (file)
@@ -71,6 +71,14 @@ sub clone_and_inherit_options {
         $actual_options{handles} = $options{handles};
         delete $options{handles};
     }
+    
+    # handles can only be added, not changed
+    if ($options{builder}) {
+        confess "You can only add the 'builder' option, you cannot change it"
+            if $self->has_builder;
+        $actual_options{builder} = $options{builder};
+        delete $options{builder};
+    }    
 
     # isa can be changed, but only if the
     # new type is a subtype
diff --git a/t/030_roles/017_extending_role_attrs.t b/t/030_roles/017_extending_role_attrs.t
new file mode 100644 (file)
index 0000000..9d8e4ac
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+use Test::Exception;
+
+BEGIN {
+    use_ok('Moose');
+}
+
+=pod
+
+This basically just makes sure that using +name 
+on role attributes works right. It is pretty simple
+test really, but I wanted to have one since we are 
+officially supporting the feature now.
+
+=cut
+
+{
+    package Foo::Role;
+    use Moose::Role;
+    
+    has 'bar' => (
+        is      => 'rw',
+        isa     => 'Int',   
+        default => sub { 10 },
+    );
+    
+    package Foo;
+    use Moose;
+    
+    with 'Foo::Role';
+    
+    ::lives_ok {
+        has '+bar' => (default => sub { 100 });
+    } '... extended the attribute successfully';  
+}
+
+my $foo = Foo->new;
+isa_ok($foo, 'Foo');
+
+is($foo->bar, 100, '... got the extended attribute');
+