+0.08 Mon Dec 09 19:00:00 EST 2008
+ - Added experimental support for recursive type constraints. Pod and
+ tests for this feature. Let the madness begin.
+ - Documentation updates.
+ - Workaround test case for the SUb::Exporter compatibility issue. Also
+ documented in Pod.
0.07 Fri Oct 07 23:00:00 EST 2008
- Bumped minimum allowed Moose version to fix problem with overloading
use namespace::clean -except => [qw( meta )];
use 5.008;
-our $VERSION = 0.07;
+our $VERSION = 0.08;
my $UndefMsg = q{Action for type '%s' not yet defined in library '%s'};
=head1 SYNOPSIS
A message that will be thrown when type functionality is used but the
type does not yet exist.
+=head1 RECURSIVE SUBTYPES
+
+As of version 0.08, L<Moose::Types> has experimental support for Recursive
+subtypes. This will allow:
+
+ subtype Tree() => as HashRef[Str|Tree];
+
+Which validates things like:
+
+ {key=>'value'};
+ {key=>{subkey1=>'value', subkey2=>'value'}}
+
+And so on. This feature is new and there may be lurking bugs so don't be afraid
+to hunt me down with patches and test cases if you have trouble.
+
=head1 NOTES REGARDING TYPE UNIONS
L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
operator and this could be an issue if you are converting code.
Patches welcome for discussion.
+
+=head2 Compatibility with Sub::Exporter
+
+If you want to use L<Sub::Exporter> with a Type Library, you need to make sure
+you export all the type constraints declared AS WELL AS any additional export
+targets. For example if you do:
+
+ package TypeAndSubExporter; {
+
+ use MooseX::Types::Moose qw(Str);
+ use MooseX::Types -declare => [qw(MyStr)];
+ use Sub::Exporter -setup => { exports => [ qw(something) ] };
+
+ subtype MyStr,
+ as Str;
+
+ sub something {
+ return 1;
+ }
+
+ } 1;
+
+ package Foo; {
+ use TypeAndSubExporter qw(MyStr);
+ } 1;
+
+You'll get a '"MyStr" is not exported by the TypeAndSubExporter module' error.
+Upi can workaround by:
+
+ - use Sub::Exporter -setup => { exports => [ qw(something) ] };
+ + use Sub::Exporter -setup => { exports => [ qw(something MyStr) ] };
+
+This is a workaround and I am exploring how to make these modules work better
+together. I realize this workaround will lead a lot of duplication in your
+export declarations and will be onerous for large type libraries. Patches and
+detailed test cases welcome. See the tests directory for a start on this.
=head1 SEE ALSO
=cut
sub AUTOLOAD {
+
my ($self, @args) = @_;
my ($method) = (our $AUTOLOAD =~ /([^:]+)$/);
- if($self->__type_constraint->can($method)) {
- return $self->__type_constraint->$method(@args);
+
+ ## We delegate with this method in an attempt to support a value of
+ ## __type_constraint which is also AUTOLOADing, in particular the class
+ ## MooseX::Types::UndefinedType which AUTOLOADs during autovivication.
+
+ my $return;
+
+ eval {
+ $return = $self->__type_constraint->$method(@args);
+ }; if($@) {
+ croak $@;
} else {
- croak "Method '$method' is not supported for ". ref($self->__type_constraint);
+ return $return;
}
}
use warnings;
use strict;
+use Moose::Util::TypeConstraints ();
+use Carp::Clan qw( ^MooseX::Types );
+
use overload '""' => sub { shift->name },
fallback => 1;
It will then return an instance of this class, handling only
stringification, name and possible identification of undefined types.
+Later, when you try to use the Undefined Type Constraint, autovivification will
+be attempted.
+
=head1 METHODS
=head2 new
=cut
-sub new { bless { name => $_[1] }, $_[0] }
+sub new {
+ return bless { name => $_[1] }, $_[0];
+}
=head2 name
=cut
-sub name { $_[0]->{name} }
+sub name {
+ return $_[0]->{name};
+}
+
+=head2 __autovivify
+
+Try to see if the type constraint has yet been defined and if so create it.
+
+=cut
+
+sub __autovivify {
+ my ($self) = @_;
+ if(my $tc = $self->{instance}) {
+ return $tc;
+ } elsif( my $new_tc = Moose::Util::TypeConstraints::find_type_constraint($self->name)) {
+ $self->{instance} = $new_tc;
+ return $new_tc;
+ } else {
+ return;
+ }
+}
+
+=head2 AUTOLOAD
+
+Try to autovivify and delegate
+
+=cut
+
+sub AUTOLOAD {
+ my ($self, @args) = @_;
+ my ($method) = our $AUTOLOAD =~ /([^:]+)$/;
+
+ if(my $type_constraint = $self->__autovivify) {
+ return $type_constraint->$method(@args);
+ } else {
+ croak "Method '$method' is not supported for " . $self->name;
+ }
+}
+
+=head2 DESTROY
+
+Moose::Meta::TypeConstraint::Parameterizable complains if this isn't here. TODO
+to find out why.
+
+=cut
+
+sub DESTROY {
+ return;
+}
=head1 SEE ALSO
L<MooseX::Types::Moose>,
L<Moose::Util::TypeConstraints>,
-L<Moose::Meta::TypeConstraint>
+L<Moose::Meta::TypeConstraint>,
+L<Carp::Clan>
=head1 AUTHOR AND COPYRIGHT
Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
the C<#moose> cabal on C<irc.perl.org>.
+Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>
+
=head1 LICENSE
This program is free software; you can redistribute it and/or modify
: ( tests => 3 );
}
-use SubExporterCompatibility qw(MyStr);
-
+use SubExporterCompatibility qw(MyStr something);
+
ok MyStr->check('aaa'), "Correctly passed";
ok !MyStr->check([1]), "Correctly fails";
-ok something(), "Found the something method";
-
+ok something(), "Found the something method";
\ No newline at end of file
package MooseX::Types::Test::Recursion::TestRunner;
BEGIN {
- use Test::More 'no_plan';
- use Data::Dump qw/dump/;
+ use Test::More tests=>5;
+ use Test::Exception;
+ ## Grab the newly created test type constraint
MooseX::Types::Test::Recursion->import(':all');
};
ok RecursiveHashRef->check({key=>{subkey=>"value"}})
=> 'properly validated {key=>{subkey=>"value"}}';
+ ok RecursiveHashRef->check({
+ key=>{
+ subkey=>"value",
+ subkey2=>{
+ ssubkey1=>"value3",
+ ssubkey2=>"value4"
+ }
+ }
+ }) => 'properly validated deeper recursive values';
+
+ ok ! RecursiveHashRef->check({key=>[1,2,3]})
+ => 'Properly invalidates bad value';
- warn dump RecursiveHashRef();
+ ok ! RecursiveHashRef->check({key=>{subkey=>"value",subkey2=>{ssubkey=>[1,2,3]}}})
+ => 'Properly invalidates bad value deeply';
}
use MooseX::Types::Moose qw(Str);
use MooseX::Types -declare => [qw(MyStr)];
- use Sub::Exporter -setup => { exports => [ qw(something) ] };
+ use Sub::Exporter -setup => { exports => [ qw(something MyStr) ] };
subtype MyStr,
as Str;