make it less easy to want moose stringy types
John Napiorkowski [Fri, 3 Apr 2015 18:23:08 +0000 (13:23 -0500)]
Changes
lib/Catalyst/Action.pm
lib/Catalyst/Controller.pm
lib/Catalyst/RouteMatching.pod
t/arg_constraints.t

diff --git a/Changes b/Changes
index 6754e7c..e6049cb 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,16 @@
 # This file documents the revision history for Perl extension Catalyst.
 
-5.90089_001 - TBA
+5.90089_002 - 2015-04-03
+  - Changed the way we check for presence of Type::Tiny in a test case to be
+    more explicit in the version requirement.  Hopefully a fix for reported
+    test fail.
+  - When declaring type constraints in Args and CaptureArgs, if you want to
+    use a Moose builtin type (or a custom stringy type that you've already
+    defined and associated with the Moose::TypeRegistry) you must now quote
+    the type name.  This is to clearly disambiguate between Moose stringy types
+    and imported types.
+
+5.90089_001 - 2015-03-26
   - New development branch synched with 5.90085.
   - New Feature: Type Constraints on Args/CaptureArgs.  Allows you to declare
     a Moose, MooseX::Types or Type::Tiny named constraint on your Arg or 
index ec30c7a..b5e75d4 100644 (file)
@@ -92,6 +92,7 @@ has number_of_args_constraints => (
         } else {
           # Its a Reftype but we don't know the number of params it
           # actually validates.
+          warn "Your type constraint '$tc' is a reference type but I cannot determine its number of parameters in action ${\$self->private_path}";
           return undef;
         }
       } else {
@@ -211,8 +212,11 @@ has captures_constraints => (
 sub resolve_type_constraint {
   my ($self, $name) = @_;
   my @tc = eval "package ${\$self->class}; $name";
-  return @tc if $tc[0];
-  return Moose::Util::TypeConstraints::find_or_parse_type_constraint($name);
+  if($tc[0]) {
+    return map { ref($_) ? $_ : Moose::Util::TypeConstraints::find_or_parse_type_constraint($_) } @tc;
+  } else {
+    return;
+  }
 }
 
 has number_of_captures => (
@@ -408,8 +412,7 @@ makes the chain not match (and alternate, less preferred chains will be attempte
 
 =head2 match_args($c, $args)
 
-Underlying feature that does the 'match' work, but doesn't require a context to
-work (like 'match' does.).
+Does the Args match or not?
 
 =head2 resolve_type_constraint
 
index 87f6df0..820eaed 100644 (file)
@@ -892,6 +892,12 @@ them into the controller namespace:
       my ($self, $c, $int) = @_;
     }
 
+If you choose not to use imported type constraints (like L<Type::Tiny>, or <MooseX::Types>
+you may use L<Moose> 'stringy' types however just like when you use these types in your
+declared attributes you must quote them:
+
+    sub my_moose_type :Local Args('Int') { ... }
+
 See L<Catalyst::RouteMatching> for more.
 
 =head2 Consumes('...')
index 5867368..e91b560 100644 (file)
@@ -23,7 +23,7 @@ is a simple example:
 
     extends 'Catalyst::Controller';
 
-    sub find :Path('') Args(Int) {
+    sub find :Path('') Args('Int') {
       my ($self, $c, $int) = @_;
     }
 
@@ -42,11 +42,18 @@ easily understood and declarative actions.
 More than one argument may be added by comma separating your type constraint names, for
 example:
 
+    use Types::Standard qw/Int Str/;
+
     sub find :Path('') Args(Int,Int,Str) {
       my ($self, $c, $int1, $int2, $str) = @_;
     }
 
-Would require three arguments, an integer, integer and a string.
+Would require three arguments, an integer, integer and a string.  Note in this example we
+constrained the args using imported types via L<Types::Standard>.  Although you may use
+stringy Moose types, we recommend imported types since this is less ambiguous to your readers.
+If you want to use Moose stringy types. you must quote them (either "Int" or 'Int' is fine).
+
+Conversely, you should not quote types that are imported!
 
 =head3 Using type constraints in a controller
 
@@ -60,7 +67,7 @@ the L<Types::Standard> library that is packaged with L<Type::Tiny>:
 
     use Moose;
     use MooseX::MethodAttributes;
-    use Types::Standard qw/StrMatch/;
+    use Types::Standard qw/StrMatch Int/;
     
     extends 'Catalyst::Controller';
 
@@ -111,6 +118,8 @@ Using type constraints in Chained actions works the same as it does for Path and
 actions.  The only difference is that you may declare type constraints on CaptureArgs as
 well as Args.  For Example:
 
+  use Types::Standard qw/Int Tuple/;
+  
   sub chain_base :Chained(/) CaptureArgs(1) { }
 
     sub any_priority_chain :GET Chained(chain_base) PathPart('') Args(1) {  }
index 4c29a43..95b92b0 100644 (file)
@@ -82,6 +82,11 @@ BEGIN {
     $c->res->body("name: $user->{name}, age: $user->{age}");
   }
 
+  sub stringy_enum :Local Args('Int',Int) {
+    my ($self, $c) = @_;
+    $c->res->body('enum');
+  }
+
   sub an_int :Local Args(Int) {
     my ($self, $c, $int) = @_;
     $c->res->body('an_int');
@@ -365,6 +370,21 @@ SKIP: {
     is $res->content, 'chained_zero2', "request POST '/chain_base2/capture'";
 }
 
+{
+    my $res = request '/stringy_enum/1/2';
+    is $res->content, 'enum', "request '/stringy_enum/a'";
+}
+
+{
+    my $res = request '/stringy_enum/b/2';
+    is $res->content, 'default', "request '/stringy_enum/a'";
+}
+
+{
+    my $res = request '/stringy_enum/1/a';
+    is $res->content, 'default', "request '/stringy_enum/a'";
+}
+
 =over
 
 | /chain_base/*/*/*/*/*/*                 | /chain_base (1)