# 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
} 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 {
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 => (
=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
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('...')
extends 'Catalyst::Controller';
- sub find :Path('') Args(Int) {
+ sub find :Path('') Args('Int') {
my ($self, $c, $int) = @_;
}
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
use Moose;
use MooseX::MethodAttributes;
- use Types::Standard qw/StrMatch/;
+ use Types::Standard qw/StrMatch Int/;
extends 'Catalyst::Controller';
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) { }
$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');
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)