[Moose-commits] r7829 - in MooseX-Types-Structured/trunk: lib/MooseX/Types t

jnapiorkowski at code2.0beta.co.uk jnapiorkowski at code2.0beta.co.uk
Fri Mar 6 20:27:42 GMT 2009


Author: jnapiorkowski
Date: 2009-03-06 12:27:41 -0800 (Fri, 06 Mar 2009)
New Revision: 7829

Modified:
   MooseX-Types-Structured/trunk/lib/MooseX/Types/Structured.pm
   MooseX-Types-Structured/trunk/t/11-overflow.t
Log:
slurpy can only slurp type constraints that match the containing type (too much crazyness to do otherwise when dealing with hashrefs and unbalanced lengths).  Cleanedup the tests and created documentation for the feature.

Modified: MooseX-Types-Structured/trunk/lib/MooseX/Types/Structured.pm
===================================================================
--- MooseX-Types-Structured/trunk/lib/MooseX/Types/Structured.pm	2009-03-06 19:11:19 UTC (rev 7828)
+++ MooseX-Types-Structured/trunk/lib/MooseX/Types/Structured.pm	2009-03-06 20:27:41 UTC (rev 7829)
@@ -481,7 +481,63 @@
 
     {first=>'John', middle=>'James', last=>'Napiorkowski'}
     {first=>'Vanessa', last=>'Li'}
+
+=head1 EXPORTABLE SUBROUTINES
+
+This type library makes available for export the following subroutines
+
+=head2 slurpy
+
+Structured type constraints by their nature are closed; that is validation will
+depend and an exact match between your structure definition and the arguments to
+be checked.  Sometimes you might wish for a slightly looser amount of validation.
+For example, you may wish to validate the first 3 elements of an array reference
+and allow for an arbitrary number of additional elements.  At first thought you
+might think you could do it this way:
+
+    #  I want to validate stuff like: [1,"hello", $obj, 2,3,4,5,6,...]
+    subtype AllowTailingArgs,
+     as Tuple[
+       Int,
+       Str,
+       Object,
+       ArrayRef[Int],
+     ];
+
+However what this will actually validate are structures like this:
+
+    [10,"Hello", $obj, [11,12,13,...] ]; # Notice element 4 is an ArrayRef
+
+In order to allow structured validation of, "and then some", arguments, you can
+use the </slurpy> method against a type constraint.  For example:
+
+    use MooseX::Types::Structured qw(Tuple slurpy);
     
+    subtype AllowTailingArgs,
+     as Tuple[
+       Int,
+       Str,
+       Object,
+       slurpy ArrayRef[Int],
+     ];
+
+This will now work as expected, validating ArrayRef structures such as:
+
+    [1,"hello", $obj, 2,3,4,5,6,...]
+    
+A few caveats apply.  First, the slurpy type constraint must be the last one in
+the list of type constraint parameters.  Second, the parent type of the slurpy
+type constraint must match that of the containing type constraint.  That means
+that a Tuple can allow a slurpy ArrayRef (or children of ArrayRefs, including
+another Tuple) and a Dict can allow a slurpy HashRef (or children/subtypes of
+HashRef, also including other Dict constraints).
+
+Please note the the technical way this works 'under the hood' is that the
+slurpy keywork transforms the target type constraint into a coderef.  Please do
+not try to create your own custom coderefs; always use the slurpy method.  The
+underlying technology may change in the future but the slurpy keyword will be
+supported.
+
 =head1 EXAMPLES
 
 Here are some additional example usage for structured types.  All examples can
@@ -600,7 +656,7 @@
 			## Make sure there are no leftovers.
 			if(@values) {
                 if($overflow_handler) {
-                    return $overflow_handler->(@values);
+                    return $overflow_handler->([@values]);
                 } else {
                     return;
                 }
@@ -650,7 +706,7 @@
 			## Make sure there are no leftovers.
 			if(%values) { 
                 if($overflow_handler) {
-                    return $overflow_handler->(%values);
+                    return $overflow_handler->(+{%values});
                 } else {
                     return;
                 }
@@ -693,24 +749,9 @@
 
 sub slurpy($) {
 	my $tc = shift @_;
-	## we don't want to force the TC to be a Moose::Meta::TypeConstraint, we
-	## just want to make sure it provides the minimum needed bits to function.
-	if($tc and ref $tc and $tc->can('check') and $tc->can('is_subtype_of') ) {
-		return sub {
-			if($tc->is_subtype_of('HashRef')) {
-				return $tc->check(+{@_});
-			} elsif($tc->is_subtype_of('ArrayRef')) {
-				return $tc->check([@_]);
-			} else {
-				return;
-			}
-		};		
-	} else {
-		## For now just pass it all to check and cross our fingers
-		return sub {
-			return $tc->check(@_);
-		};	
-	}
+	return sub {
+        $tc->check(shift);
+    };
 }
 
 =head1 SEE ALSO

Modified: MooseX-Types-Structured/trunk/t/11-overflow.t
===================================================================
--- MooseX-Types-Structured/trunk/t/11-overflow.t	2009-03-06 19:11:19 UTC (rev 7828)
+++ MooseX-Types-Structured/trunk/t/11-overflow.t	2009-03-06 20:27:41 UTC (rev 7829)
@@ -1,7 +1,7 @@
 BEGIN {
 	use strict;
 	use warnings;
-	use Test::More tests=>20;
+	use Test::More tests=>10;
 }
 
 use Moose::Util::TypeConstraints;
@@ -22,20 +22,6 @@
 ok $array_tailed_tuple->check([1,'hello',1,2,3,4]), 'correct pass with tail';
 ok !$array_tailed_tuple->check([1,'hello',1,2,'bad',4]), 'correct fail with tail';
 
-my $hash_tailed_tuple =
-    subtype 'hash_tailed_tuple',
-     as Tuple[
-       Int,
-       Str,
-       slurpy HashRef[Int],
-     ];
-
-ok !$hash_tailed_tuple->check(['ss',1]), 'correct fail';
-ok $hash_tailed_tuple->check([1,'ss']), 'correct pass';
-ok !$hash_tailed_tuple->check({}), 'correct fail';
-ok $hash_tailed_tuple->check([1,'hello',age=>25,zip=>10533]), 'correct pass with tail';
-ok !$hash_tailed_tuple->check([1,'hello',age=>25,name=>'john']), 'correct fail with tail';
-
 my $hash_tailed_dict =
     subtype 'hash_tailed_dict',
     as Dict[
@@ -50,6 +36,22 @@
 ok $hash_tailed_dict->check({name=>'Vanessa Li', age=>35, more1=>1,more2=>2}), 'correct pass with tail';
 ok !$hash_tailed_dict->check({name=>'Vanessa Li', age=>35, more1=>1,more2=>"aa"}), 'correct fail with tail';
 
+__END__
+
+my $hash_tailed_tuple =
+    subtype 'hash_tailed_tuple',
+     as Tuple[
+       Int,
+       Str,
+       slurpy HashRef[Int],
+     ];
+
+ok !$hash_tailed_tuple->check(['ss',1]), 'correct fail';
+ok $hash_tailed_tuple->check([1,'ss']), 'correct pass';
+ok !$hash_tailed_tuple->check({}), 'correct fail';
+ok $hash_tailed_tuple->check([1,'hello',age=>25,zip=>10533]), 'correct pass with tail';
+ok !$hash_tailed_tuple->check([1,'hello',age=>25,name=>'john']), 'correct fail with tail';
+
 my $array_tailed_dict =
     subtype 'hash_tailed_dict',
     as Dict[
@@ -61,19 +63,5 @@
 ok !$array_tailed_dict->check({name=>'john',age=>'napiorkowski'}), 'correct fail';
 ok $array_tailed_dict->check({name=>'Vanessa Li', age=>35}), 'correct pass';
 ok !$array_tailed_dict->check([]), 'correct fail';
-ok $array_tailed_dict->check({name=>'Vanessa Li', age=>35, 1,2}), 'correct pass with tail';
+ok $array_tailed_dict->check({name=>'Vanessa Li', age=>35, 1,2,3}), 'correct pass with tail';
 ok !$array_tailed_dict->check({name=>'Vanessa Li', age=>35, 1, "hello"}), 'correct fail with tail';
-
-my $insane_tc =
-	subtype 'insane_tc',
-	as Tuple[
-		Object,
-		slurpy Dict[
-			name=>Str,
-			age=>Int,
-			slurpy ArrayRef[Int],
-		]
-	];
-	
-ok $insane_tc->check([$insane_tc, name=>"John", age=>25, 1,2,3]),
-  'validated: [$insane_tc, name=>"John", age=>25, 1,2,3]';
\ No newline at end of file




More information about the Moose-commits mailing list