[Moose-commits] r7764 - in Moose/trunk: lib/Moose/Util
t/040_type_constraints t/200_examples
autarch at code2.0beta.co.uk
autarch at code2.0beta.co.uk
Sat Feb 21 22:28:18 GMT 2009
Author: autarch
Date: 2009-02-21 14:28:17 -0800 (Sat, 21 Feb 2009)
New Revision: 7764
Modified:
Moose/trunk/lib/Moose/Util/TypeConstraints.pm
Moose/trunk/t/040_type_constraints/001_util_type_constraints.t
Moose/trunk/t/200_examples/004_example_w_DCS.t
Log:
Officially document sugar-free form for type and subtype where it
accepts a hashref of named parameters, rather than positional params.
This preserves the safety of non-positional params, but lets you
integrate easily with other modules, for doing
subtype( 'Foo', { where => sub_returner() } );
Added tests for this new style and made sure the docs show it too.
Modified: Moose/trunk/lib/Moose/Util/TypeConstraints.pm
===================================================================
--- Moose/trunk/lib/Moose/Util/TypeConstraints.pm 2009-02-21 22:00:59 UTC (rev 7763)
+++ Moose/trunk/lib/Moose/Util/TypeConstraints.pm 2009-02-21 22:28:17 UTC (rev 7764)
@@ -5,7 +5,7 @@
use warnings;
use Carp ();
-use List::MoreUtils qw( all );
+use List::MoreUtils qw( all any );
use Scalar::Util qw( blessed reftype );
use Moose::Exporter;
@@ -256,17 +256,16 @@
# type constructors
sub type {
- if ( all { ( reftype($_) || '' ) eq 'CODE' || ! ref $_ } @_ ) {
- # back-compat version, called without sugar
- _create_type_constraint( $_[0], undef, $_[1] );
+ # back-compat version, called without sugar
+ if ( ! any { ( reftype($_) || '' ) eq 'HASH' } @_ ) {
+ return _create_type_constraint( $_[0], undef, $_[1] );
}
- else {
- my $name = shift;
- my %p = map { %{$_} } @_;
+ my $name = shift;
- _create_type_constraint( $name, undef, $p{check}, $p{message}, $p{optimized} );
- }
+ my %p = map { %{$_} } @_;
+
+ return _create_type_constraint( $name, undef, $p{where}, $p{message}, $p{optimize_as} );
}
sub subtype {
@@ -294,12 +293,12 @@
my %p = map { %{$_} } @_;
# subtype Str => where { ... };
- if ( ! exists $p{parent} ) {
- $p{parent} = $name;
+ if ( ! exists $p{as} ) {
+ $p{as} = $name;
$name = undef;
}
- _create_type_constraint( $name, $p{parent}, $p{check}, $p{message}, $p{optimized} );
+ return _create_type_constraint( $name, $p{as}, $p{where}, $p{message}, $p{optimize_as} );
}
sub class_type {
@@ -333,10 +332,10 @@
_install_type_coercions($type_name, \@coercion_map);
}
-sub as ($) { { parent => $_[0] } }
-sub where (&) { { check => $_[0] } }
-sub message (&) { { message => $_[0] } }
-sub optimize_as (&) { { optimized => $_[0] } }
+sub as ($) { { as => $_[0] } }
+sub where (&) { { where => $_[0] } }
+sub message (&) { { message => $_[0] } }
+sub optimize_as (&) { { optimize_as => $_[0] } }
sub from {@_}
sub via (&) { $_[0] }
@@ -836,10 +835,13 @@
For instance, this is how you could use it with
L<Declare::Constraints::Simple> to declare a completely new type.
- type 'HashOfArrayOfObjects'
- => IsHashRef(
+ type 'HashOfArrayOfObjects',
+ {
+ where => IsHashRef(
-keys => HasLength,
- -values => IsArrayRef( IsObject ));
+ -values => IsArrayRef(IsObject)
+ )
+ };
For more examples see the F<t/200_examples/204_example_w_DCS.t>
test file.
@@ -875,9 +877,14 @@
This creates a base type, which has no parent.
-Note that calling C<type> I<without> the sugar helpers (C<where>,
-C<message>, etc), is deprecated.
+The C<type> function should either be called with the sugar helpers
+(C<where>, C<message>, etc), or with a name and a hashref of
+parameters:
+ type( 'Foo', { where => ..., message => ... } );
+
+The valid hashref keys are C<where>, C<message>, and C<optimize_as>.
+
=item B<subtype 'Name' => as 'Parent' => where { } ...>
This creates a named subtype.
@@ -885,15 +892,27 @@
If you provide a parent that Moose does not recognize, it will
automatically create a new class type constraint for this name.
-Note that calling C<subtype> I<without> the sugar helpers (C<where>,
-C<message>, etc), is deprecated.
+When creating a named type, the C<subtype> function should either be
+called with the sugar helpers (C<where>, C<message>, etc), or with a
+name and a hashref of parameters:
+ subtype( 'Foo', { where => ..., message => ... } );
+
+The valid hashref keys are C<as> (the parent), C<where>, C<message>,
+and C<optimize_as>.
+
=item B<subtype as 'Parent' => where { } ...>
This creates an unnamed subtype and will return the type
constraint meta-object, which will be an instance of
L<Moose::Meta::TypeConstraint>.
+When creating an anonymous type, the C<subtype> function should either
+be called with the sugar helpers (C<where>, C<message>, etc), or with
+just a hashref of parameters:
+
+ subtype( { where => ..., message => ... } );
+
=item B<class_type ($class, ?$options)>
Creates a new subtype of C<Object> with the name C<$class> and the
Modified: Moose/trunk/t/040_type_constraints/001_util_type_constraints.t
===================================================================
--- Moose/trunk/t/040_type_constraints/001_util_type_constraints.t 2009-02-21 22:00:59 UTC (rev 7763)
+++ Moose/trunk/t/040_type_constraints/001_util_type_constraints.t 2009-02-21 22:28:17 UTC (rev 7764)
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 73;
+use Test::More tests => 84;
use Test::Exception;
use Scalar::Util ();
@@ -161,6 +161,31 @@
ok( $subtype->has_message, 'subtype does have a message' );
}
+# alternative sugar-less calling style which is documented as legit:
+{
+ my $subtype = subtype( 'MyStr', { as => 'Str' } );
+ isa_ok( $subtype, 'Moose::Meta::TypeConstraint', 'got a subtype' );
+ is( $subtype->name, 'MyStr', 'name is MyStr' );
+ is( $subtype->parent->name, 'Str', 'parent is Str' );
+}
+
+{
+ my $subtype = subtype( { as => 'Str' } );
+ isa_ok( $subtype, 'Moose::Meta::TypeConstraint', 'got a subtype' );
+ is( $subtype->name, '__ANON__', 'name is __ANON__' );
+ is( $subtype->parent->name, 'Str', 'parent is Str' );
+}
+
+{
+ my $subtype = subtype( { as => 'Str', where => sub { /X/ } } );
+ isa_ok( $subtype, 'Moose::Meta::TypeConstraint', 'got a subtype' );
+ is( $subtype->name, '__ANON__', 'name is __ANON__' );
+ is( $subtype->parent->name, 'Str', 'parent is Str' );
+ ok( $subtype->check('FooX'), 'constraint accepts FooX' );
+ ok( ! $subtype->check('Foo'), 'constraint reject Foo' );
+}
+
+
# Back-compat for being called without sugar. Previously, calling with
# sugar was indistinguishable from calling directly.
Modified: Moose/trunk/t/200_examples/004_example_w_DCS.t
===================================================================
--- Moose/trunk/t/200_examples/004_example_w_DCS.t 2009-02-21 22:00:59 UTC (rev 7763)
+++ Moose/trunk/t/200_examples/004_example_w_DCS.t 2009-02-21 22:28:17 UTC (rev 7764)
@@ -27,13 +27,16 @@
use Moose;
use Moose::Util::TypeConstraints;
use Declare::Constraints::Simple -All;
-
+
# define your own type ...
- type 'HashOfArrayOfObjects'
- => IsHashRef(
+ type( 'HashOfArrayOfObjects',
+ {
+ where => IsHashRef(
-keys => HasLength,
- -values => IsArrayRef( IsObject ));
-
+ -values => IsArrayRef(IsObject)
+ )
+ } );
+
has 'bar' => (
is => 'rw',
isa => 'HashOfArrayOfObjects',
@@ -42,7 +45,7 @@
# inline the constraints as anon-subtypes
has 'baz' => (
is => 'rw',
- isa => subtype('ArrayRef' => IsArrayRef(IsInt)),
+ isa => subtype( { as => 'ArrayRef', where => IsArrayRef(IsInt) } ),
);
package Bar;
More information about the Moose-commits
mailing list