basic coerces
John Napiorkowski [Tue, 17 Mar 2015 17:51:43 +0000 (12:51 -0500)]
lib/Catalyst/Action.pm
t/arg_constraints.t

index 274ffd9..6081f22 100644 (file)
@@ -147,14 +147,19 @@ sub match {
 
     # There there are arg constraints, we must see to it that the constraints
     # check positive for each arg in the list.
-    if($self->has_args_constraints) {
+    if(0 && $self->has_args_constraints) {
       # If there is only one type constraint, and its a Ref or subtype of Ref,
       # That means we expect a reference, so use the full args arrayref.
       if(
         $self->number_of_args_constraints == 1 &&
-        $self->args_constraints->[0]->is_a_type_of('Ref')
+        ($self->args_constraints->[0]->is_a_type_of('Ref') || $self->args_constraints->[0]->is_a_type_of('ClassName'))
       ) {
-        return $self->args_constraints->[0]->check($c->req->args);
+        return 1 if $self->args_constraints->[0]->check($c->req->args);
+        if($self->args_constraints->[0]->coercion && $self->attributes->{Coerce}) {
+          my $coerced = $self->args_constraints->[0]->coerce($c) || return 0;
+          $c->req->args([$coerced]);
+          return 1;
+        }
       } else {
         for my $i(0..$#{ $c->req->args }) {
           $self->args_constraints->[$i]->check($c->req->args->[$i]) || return 0;
@@ -239,6 +244,9 @@ of the captures for this action.
 Returning true from this method causes the chain match to continue, returning
 makes the chain not match (and alternate, less preferred chains will be attempted).
 
+=head2 resolve_type_constraint
+
+Trys to find a type constraint if you have on on a type constrained method.
 
 =head2 compare
 
index 2a43a87..2a6636e 100644 (file)
@@ -6,18 +6,72 @@ BEGIN {
   eval "use Types::Standard; 1;" || do {
     plan skip_all => "Trouble loading Types::Standard => $@";
   };
+
+  package MyApp::Types;
+  $INC{'MyApp/Types.pm'} = __FILE__;
+
+  use strict;
+  use warnings;
+  use Type::Utils -all;
+  use Types::Standard -types;
+  use Type::Library
+   -base,
+   -declare => qw( UserId User ContextLike );
+
+  extends "Types::Standard"; 
+
+  class_type User, { class => "MyApp::Model::User::user" };
+  duck_type ContextLike, [qw/model/];
+
+  declare UserId,
+   as Int,
+   where { $_ < 5 };
+
+  coerce User,
+   from ContextLike,
+     via { $_->model('User')->find( $_->req->args->[0] ) };
 }
 
 {
+  package MyApp::Model::User;
+  $INC{'MyApp/Model/User.pm'} = __FILE__;
+
+  use base 'Catalyst::Model';
+
+  our %users = (
+    1 => { name => 'john', age => 46 },
+    2 => { name => 'mary', age => 36 },
+    3 => { name => 'ian', age => 25 },
+    4 => { name => 'visha', age => 18 },
+  );
+
+  sub find {
+    my ($self, $id) = @_;
+    my $user = $users{$id} || return;
+    return bless $user, "MyApp::Model::User::user";
+  }
+
   package MyApp::Controller::Root;
   $INC{'MyApp/Controller/Root.pm'} = __FILE__;
 
   use Moose;
   use MooseX::MethodAttributes;
-  use Types::Standard qw/Tuple Int Str/;
+  use MyApp::Types qw/Tuple Int Str StrMatch UserId User/;
 
   extends 'Catalyst::Controller';
 
+  sub user :Local Args(UserId) {
+    my ($self, $c, $int) = @_;
+    my $user = $c->model("User")->find($int);
+    $c->res->body("name: $user->{name}, age: $user->{age}");
+  }
+
+  sub user_object :Local Args(User) Coerce(1) {
+    my ($self, $c, $user) = @_;
+    $c->res->body("name: $user->{name}, age: $user->{age}");
+  }
+
   sub an_int :Local Args(Int) {
     my ($self, $c, $int) = @_;
     $c->res->body('an_int');
@@ -29,11 +83,15 @@ BEGIN {
   }
 
   sub tuple :Local Args(Tuple[Str,Int]) {
-    my ($self, $c, $int) = @_;
+    my ($self, $c, $str, $int) = @_;
+    warn "$str $int";
     $c->res->body('tuple');
   }
 
-
+  sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
+    my ($self, $c, $int) = @_;
+    $c->res->body('match');
+  }
   sub any_priority :Path('priority_test') Args(1) { $_[1]->res->body('any_priority') }
 
   sub int_priority :Path('priority_test') Args(Int) { $_[1]->res->body('int_priority') }
@@ -48,7 +106,6 @@ BEGIN {
   package MyApp;
   use Catalyst;
 
-  #MyApp->config(show_internal_actions => 1);
   MyApp->setup;
 }
 
@@ -104,5 +161,34 @@ use Catalyst::Test 'MyApp';
   is $res->content, 'default';
 }
 
-done_testing;
+{
+  my $res = request '/match/11-22-33';
+  is $res->content, 'match';
+}
 
+{
+  my $res = request '/match/aaa';
+  is $res->content, 'default';
+}
+
+{
+  my $res = request '/user/2';
+  is $res->content, 'name: mary, age: 36';
+}
+
+{
+  my $res = request '/user/20';
+  is $res->content, 'default';
+}
+
+{
+  my $res = request '/user_object/20';
+  is $res->content, 'default';
+}
+
+{
+  my $res = request '/user_object/2';
+  is $res->content, 'name: mary, age: 36';
+}
+
+done_testing;