X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMooseX%2FTypes%2FStructured.pm;h=eff3c0c8b956030f2bfaa0a18c62f8ebc7294b00;hb=5fd2fb5a1335d0ac0b1f8c0266fe0324ebec1e8b;hp=37b2efc33acc768be3c19636079039da684f73fc;hpb=662be9101e0ae369511692ec54d9a9922965d219;p=gitmo%2FMooseX-Types-Structured.git diff --git a/lib/MooseX/Types/Structured.pm b/lib/MooseX/Types/Structured.pm index 37b2efc..eff3c0c 100644 --- a/lib/MooseX/Types/Structured.pm +++ b/lib/MooseX/Types/Structured.pm @@ -1,12 +1,12 @@ package MooseX::Types::Structured; +use 5.8.8; use Moose; use Moose::Util::TypeConstraints; use MooseX::Meta::TypeConstraint::Structured; use MooseX::Types -declare => [qw(Dict Tuple)]; - -our $VERSION = '0.02'; +our $VERSION = '0.03'; our $AUTHORITY = 'cpan:JJNAPIORK'; =head1 NAME @@ -43,29 +43,35 @@ Please see the test cases for more examples. A structured type constraint is a standard container L type constraint, such as an arrayref or hashref, which has been enhanced to allow you to -explicitely name all the allow type constraints inside the structure. The +explicitly name all the allow type constraints inside the structure. The generalized form is: TypeConstraint[TypeParameters] Where TypeParameters is a list of type constraints. -This type library enables structured type constraints. These work in a similar -way to parameterized constraints that are built into the core Moose types, -except that you are allowed to define the container's entire structure. For -example, you could define a parameterized constraint like so: +This type library enables structured type constraints. It is build on top of the +L library system, so you should review the documentation for that +if you are not familiar with it. + +=head2 Comparing Parameterized types to Structured types + +Parameterized constraints are built into the core Moose types 'HashRef' and +'ArrayRef'. Structured types have similar functionality, so their syntax is +likewise similar. For example, you could define a parameterized constraint like: subtype HashOfInts, as Hashref[Int]; which would constraint a value to something like [1,2,3,...] and so on. On the -other hand, a structured type constrain explicitly names all it's allowed type +other hand, a structured type constraint explicitly names all it's allowed type parameter constraints. For the example: subtype StringFollowedByInt, as Tuple[Str,Int]; -would constrain it's value to something like ['hello', 111]; +would constrain it's value to something like ['hello', 111] but ['hello', 'world'] +would fail, as well as ['hello', 111, 'world'] These structures can be as simple or elaborate as you wish. You can even combine various structured, parameterized and simple constraints all together: @@ -78,7 +84,11 @@ combine various structured, parameterized and simple constraints all together: ]; Which would match "[1, {name=>'John', age=>25},[10,11,12]]". Please notice how -the type parameters +the type parameters can be visually arranged to your liking and to improve the +clarity of your meaning. You don't need to run then altogether onto a single +line. + +=head2 Alternatives You should exercise some care as to whether or not your complex structured constraints would be better off contained by a real object as in the following @@ -107,16 +117,12 @@ method, granting some interesting possibilities for coercion. Try: coerce 'MyStruct', from (Dict[name=>Str, age=>Int]), - via { - MyApp::MyStruct->new(%$_); - }, + via { MyApp::MyStruct->new(%$_) }, from (Dict[last_name=>Str, first_name=>Str, dob=>DateTime]), via { my $name = $_->{first_name} .' '. $_->{last_name}; my $age = DateTime->now - $_->{dob}; - MyApp::MyStruct->new( - name=>$name, - age=>$age->years ); + MyApp::MyStruct->new( name=>$name, age=>$age->years ); }; =head2 Subtyping a structured subtype @@ -132,10 +138,10 @@ as in this example: This will actually work BUT you have to take care that the subtype has a structure that does not contradict the structure of it's parent. For now the -above works, but I will probably clarify how this works at a future point, so +above works, but I will clarify the syntax for this at a future point, so it's recommended to avoid (should not realy be needed so much anyway). For -now this is supported in an EXPERIMENTAL way. In the future we will probably -clarify how to augment existing structured types. +now this is supported in an EXPERIMENTAL way. Your thoughts, test cases and +patches are welcomed for discussion. =head2 Coercions @@ -186,6 +192,45 @@ hashref. For example: Dict[name=>Str, age=>Int]; ## Validates {name=>'John', age=>39} +=head1 EXAMPLES + +Here are some additional example usage for structured types. All examples can +be found also in the 't/examples.t' test. Your contributions are also welcomed. + +=head2 Normalize a HashRef + +You need a hashref to conform to a canonical structure but are required accept a +bunch of different incoming structures. You can normalize using the Dict type +constraint and coercions. This example also shows structured types mixed which +other MooseX::Types libraries. + + package Test::MooseX::Meta::TypeConstraint::Structured::Examples::Normalize; + + use Moose; + use DateTime; + + use MooseX::Types::Structured qw(Dict Tuple); + use MooseX::Types::DateTime qw(DateTime); + use MooseX::Types::Moose qw(Int Str Object); + use MooseX::Types -declare => [qw(Name Age Person)]; + + subtype Person, + as Dict[name=>Str, age=>Int]; + + coerce Person, + from Dict[first=>Str, last=>Str, years=>Int], + via { +{ + name => "$_->{first} $_->{last}", + age=>$_->{years}, + }}, + from Dict[fullname=>Dict[last=>Str, first=>Str], dob=>DateTime], + via { +{ + name => "$_->{fullname}{first} $_->{fullname}{last}", + age => ($_->{dob} - 'DateTime'->now)->years, + }}; + + has person => (is=>'rw', isa=>Person, coerce=>1); + =cut Moose::Util::TypeConstraints::get_type_constraint_registry->add_type_constraint( @@ -237,15 +282,6 @@ Moose::Util::TypeConstraints::get_type_constraint_registry->add_type_constraint( delete $values{$key}; unless($type_constraint->check($value)) { return; - #if ($type_constraint->has_coercion) { - # my $temp = $type_constraint->coerce($value); - # use Data::Dump qw/dump/; warn dump $value, $temp; - # unless($type_constraint->check($temp)) { - # return; - # } - #} else { - # return; - #} } } else { return;