From: Stevan Little Date: Thu, 24 May 2007 21:30:30 +0000 (+0000) Subject: adding support for checking container types in the constructor X-Git-Tag: 0.18_01~78 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=77d02b8b55108cc6819c456152fc2d504c5cd069;hp=8a6b3adde88036ee3ce2530103d884464f9e5e42;p=gitmo%2FMooseX-AttributeHelpers.git adding support for checking container types in the constructor --- diff --git a/lib/MooseX/AttributeHelpers/Collection.pm b/lib/MooseX/AttributeHelpers/Collection.pm index d821b15..12c3d99 100644 --- a/lib/MooseX/AttributeHelpers/Collection.pm +++ b/lib/MooseX/AttributeHelpers/Collection.pm @@ -15,28 +15,9 @@ has 'container_type' => ( ); has 'container_type_constraint' => ( - is => 'rw', - isa => 'Moose::Meta::TypeConstraint', - lazy => 1, - default => sub { - my $self = shift; - ($self->has_container_type) - || confess "You cannot create a container_type_constraint if you dont have a container type"; - - my $container_type = $self->container_type; - my $constraint = find_type_constraint($container_type); - - # NOTE: - # I am not sure DWIM-ery is a good thing - # here, so i am going to err on the side - # of caution, and blow up if you have - # not made a type constraint for this yet. - # - SL - (defined $constraint) - || confess "You must predefine the '$container_type' constraint before you can use it as a container type"; - - return $constraint; - } + is => 'rw', + isa => 'Moose::Meta::TypeConstraint', + required => 1, ); before 'process_options_for_provides' => sub { @@ -44,11 +25,44 @@ before 'process_options_for_provides' => sub { if (exists $options->{isa}) { my $type = $options->{isa}; + + # ... we should check if the type exists already + # and then we should use it,.. however, this means + # we need to extract the container type constraint + # as well, which is a little trickier + if ($type =~ /^(.*)\[(.*)\]$/) { my $core_type = $1; my $container_type = $2; - $options->{isa} = $core_type; + $options->{container_type} = $container_type; + + my $container_type_constraint = find_type_constraint($container_type); + + # NOTE: + # I am not sure DWIM-ery is a good thing + # here, so i am going to err on the side + # of caution, and blow up if you have + # not made a type constraint for this yet. + # - SL + (defined $container_type_constraint) + || confess "You must predefine the '$container_type' constraint before you can use it as a container type"; + + $options->{container_type_constraint} = $container_type_constraint; + + if ($core_type eq 'ArrayRef') { + $options->{isa} = subtype('ArrayRef' => where { + foreach my $x (@$_) { ($container_type_constraint->check($x)) || return } 1; + }); + } + elsif ($core_type eq 'HashRef') { + $options->{isa} = subtype('HashRef' => where { + foreach my $x (values %$_) { ($container_type_constraint->check($x)) || return } 1; + }); + } + else { + confess "Your isa must be either ArrayRef or HashRef (sorry no subtype support yet)"; + } } } }; diff --git a/t/002_basic_array.t b/t/002_basic_array.t index 479269e..fbd7176 100644 --- a/t/002_basic_array.t +++ b/t/002_basic_array.t @@ -32,7 +32,7 @@ BEGIN { ); } -my $stuff = Stuff->new(); +my $stuff = Stuff->new(options => [ 10, 12 ]); isa_ok($stuff, 'Stuff'); can_ok($stuff, $_) for qw[ @@ -46,7 +46,15 @@ can_ok($stuff, $_) for qw[ has_options ]; -is_deeply($stuff->options, [], '... no options yet'); +is_deeply($stuff->options, [10, 12], '... got options'); + +ok($stuff->has_options, '... we have options'); +is($stuff->num_options, 2, '... got 2 options'); + +is($stuff->remove_last_option, 12, '... removed the last option'); +is($stuff->remove_first_option, 10, '... removed the last option'); + +is_deeply($stuff->options, [], '... no options anymore'); ok(!$stuff->has_options, '... no options'); is($stuff->num_options, 0, '... got no options'); @@ -113,6 +121,10 @@ dies_ok { $stuff->set_option(5, {}); } '... could not add a hash ref where an int is expected'; +dies_ok { + Stuff->new(options => [ 'Foo', 10, 'Bar', 20 ]); +} '... bad constructor params'; + ## test the meta my $options = $stuff->meta->get_attribute('options'); diff --git a/t/003_basic_hash.t b/t/003_basic_hash.t index f2f73df..164de56 100644 --- a/t/003_basic_hash.t +++ b/t/003_basic_hash.t @@ -60,10 +60,18 @@ is_deeply($stuff->options, { foo => 'bar', bar => 'baz' }, '... got more options is($stuff->get_option('foo'), 'bar', '... got the right option'); +lives_ok { + Stuff->new(options => { foo => 'BAR' }); +} '... good constructor params'; + ## check some errors dies_ok { $stuff->set_option(bar => {}); } '... could not add a hash ref where an string is expected'; +dies_ok { + Stuff->new(options => { foo => [] }); +} '... bad constructor params'; +