From: Stevan Little Date: Tue, 3 Jul 2007 15:56:19 +0000 (+0000) Subject: adding lazy and handles to the has +foo form X-Git-Tag: 0_24^0 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=83cc9094b0284849a7fb5e19833b27d3efdfd28f;p=gitmo%2FMoose.git adding lazy and handles to the has +foo form --- diff --git a/Changes b/Changes index 857e0b3..f8a4583 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,10 @@ Revision history for Perl extension Moose - added support for roles to be given as parameters to the 'handles' option. - added tests and docs for this + - the has '+foo' attribute form now accepts changes to + the lazy option, and the addition of a handles option + (but not changing the handles option) + - added tests and docs for this * Moose::Meta::Role - required methods are now fetched using find_method_by_name diff --git a/lib/Moose.pm b/lib/Moose.pm index a4e670b..bc62262 100644 --- a/lib/Moose.pm +++ b/lib/Moose.pm @@ -585,7 +585,7 @@ What is happening here is that B is cloning the C attribute from its parent class B, retaining the C 'rw'> and C 'Str'> characteristics, but changing the value in C. -This feature is restricted somewhat, so as to try and enfore at least I +This feature is restricted somewhat, so as to try and force at least I sanity into it. You are only allowed to change the following attributes: =over 4 @@ -606,11 +606,20 @@ Change if the attribute is required to have a value. Change the documentation string associated with the attribute. +=item I + +Change if the attribute lazily initializes the slot. + =item I You I allowed to change the type, B the new type is a subtype of the old type. +=item I + +You are allowed to B a new C definition, but you are B +allowed to I one. + =back =item B sub { ... }> diff --git a/lib/Moose/Meta/Attribute.pm b/lib/Moose/Meta/Attribute.pm index a8365a4..c1613da 100644 --- a/lib/Moose/Meta/Attribute.pm +++ b/lib/Moose/Meta/Attribute.pm @@ -52,14 +52,23 @@ sub new { sub clone_and_inherit_options { my ($self, %options) = @_; - # you can change default, required, coerce and documentation + # you can change default, required, coerce, documentation and lazy my %actual_options; - foreach my $legal_option (qw(default coerce required documentation)) { + foreach my $legal_option (qw(default coerce required documentation lazy)) { if (exists $options{$legal_option}) { $actual_options{$legal_option} = $options{$legal_option}; delete $options{$legal_option}; } } + + # handles can only be added, not changed + if ($options{handles}) { + confess "You can only add the 'handles' option, you cannot change it" + if $self->has_handles; + $actual_options{handles} = $options{handles}; + delete $options{handles}; + } + # isa can be changed, but only if the # new type is a subtype if ($options{isa}) { diff --git a/t/038_attribute_inherited_slot_specs.t b/t/038_attribute_inherited_slot_specs.t index 88eb18b..791f042 100644 --- a/t/038_attribute_inherited_slot_specs.t +++ b/t/038_attribute_inherited_slot_specs.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 57; +use Test::More tests => 72; use Test::Exception; BEGIN { @@ -11,6 +11,12 @@ BEGIN { } { + package Thing; + use Moose; + + sub hello { 'Hello World (from Thing)' } + sub goodbye { 'Goodbye World (from Thing)' } + package Foo; use Moose; use Moose::Util::TypeConstraints; @@ -27,7 +33,11 @@ BEGIN { has 'baz' => (is => 'rw', isa => 'Ref'); has 'foo' => (is => 'rw', isa => 'FooStr'); - has 'gorch' => (is => 'ro'); + has 'gorch' => (is => 'ro'); + has 'gloum' => (is => 'ro', default => sub {[]}); + + has 'bling' => (is => 'ro', isa => 'Thing'); + has 'blang' => (is => 'ro', isa => 'Thing', handles => ['goodbye']); # this one will work here .... has 'fail' => (isa => 'CodeRef'); @@ -37,14 +47,35 @@ BEGIN { use Moose; extends 'Foo'; + + ::lives_ok { + has '+bar' => (default => 'Bar::bar'); + } '... we can change the default attribute option'; + + ::lives_ok { + has '+baz' => (isa => 'ArrayRef'); + } '... we can add change the isa as long as it is a subtype'; - has '+bar' => (default => 'Bar::bar'); - has '+baz' => (isa => 'ArrayRef'); + ::lives_ok { + has '+foo' => (coerce => 1); + } '... we can change/add coerce as an attribute option'; + + ::lives_ok { + has '+gorch' => (required => 1); + } '... we can change/add required as an attribute option'; + + ::lives_ok { + has '+gloum' => (lazy => 1); + } '... we can change/add lazy as an attribute option'; - has '+foo' => (coerce => 1); - has '+gorch' => (required => 1); + ::lives_ok { + has '+bling' => (handles => ['hello']); + } '... we can add the handles attribute option'; # this one will *not* work here .... + ::dies_ok { + has '+blang' => (handles => ['hello']); + } '... we can not alter the handles attribute option'; ::dies_ok { has '+fail' => (isa => 'Ref'); } '... cannot create an attribute with an improper subtype relation'; @@ -54,9 +85,6 @@ BEGIN { ::dies_ok { has '+other_fail' => (weak_ref => 1); } '... cannot create an attribute with an illegal option'; - ::dies_ok { - has '+other_fail' => (lazy => 1); - } '... cannot create an attribute with an illegal option'; } @@ -134,6 +162,9 @@ ok(Bar->meta->has_attribute('foo'), '... Bar has a foo attr'); ok(Bar->meta->has_attribute('bar'), '... Bar has a bar attr'); ok(Bar->meta->has_attribute('baz'), '... Bar has a baz attr'); ok(Bar->meta->has_attribute('gorch'), '... Bar has a gorch attr'); +ok(Bar->meta->has_attribute('gloum'), '... Bar has a gloum attr'); +ok(Bar->meta->has_attribute('bling'), '... Bar has a bling attr'); +ok(!Bar->meta->has_attribute('blang'), '... Bar has a blang attr'); ok(!Bar->meta->has_attribute('fail'), '... Bar does not have a fail attr'); ok(!Bar->meta->has_attribute('other_fail'), '... Bar does not have a fail attr'); @@ -148,7 +179,13 @@ isnt(Foo->meta->get_attribute('baz'), '... Foo and Bar have different copies of baz'); isnt(Foo->meta->get_attribute('gorch'), Bar->meta->get_attribute('gorch'), - '... Foo and Bar have different copies of gorch'); + '... Foo and Bar have different copies of gorch'); +isnt(Foo->meta->get_attribute('gloum'), + Bar->meta->get_attribute('gloum'), + '... Foo and Bar have different copies of gloum'); +isnt(Foo->meta->get_attribute('bling'), + Bar->meta->get_attribute('bling'), + '... Foo and Bar have different copies of bling'); ok(Bar->meta->get_attribute('bar')->has_type_constraint, '... Bar::bar inherited the type constraint too'); @@ -168,9 +205,19 @@ ok(!Foo->meta->get_attribute('gorch')->is_required, ok(Bar->meta->get_attribute('gorch')->is_required, '... Bar::gorch is a required attr'); +ok(!Foo->meta->get_attribute('gloum')->is_lazy, + '... Foo::gloum is not a required attr'); +ok(Bar->meta->get_attribute('gloum')->is_lazy, + '... Bar::gloum is a required attr'); + ok(!Foo->meta->get_attribute('foo')->should_coerce, '... Foo::foo should not coerce'); ok(Bar->meta->get_attribute('foo')->should_coerce, - '... Bar::foo should coerce'); + '... Bar::foo should coerce'); + +ok(!Foo->meta->get_attribute('bling')->has_handles, + '... Foo::foo should not handles'); +ok(Bar->meta->get_attribute('bling')->has_handles, + '... Bar::foo should handles');