## MyApp/Types.pm; use MooseX::Declare::Types; use MooseX::Types::Moose qw(Str Int); use MooseX::Types::Structured qw(Dict Optional); ## Possible interface for facets, with are a bit like roles for types. This ## just a sketch, doesn't represent a lot of thought. use MooseX::Types::Facets { Str => [qw/ hasMinimumLength hasMaximumLength isWords matchesRegex/ ], }; subtype FullName { as Str; having hasMinimumLength(2), matchesPattern( strategy=>Regexp, pattern=>qr/ ^ \w{2,35} \s \w{0,25} \s* \w{2,50} $ /x ); parameter length => ( isa=>Int, default=>100 ); parameterizes($p Parameters) { having hasMaximumLength($p->length); } } subtype Name { parameter total_length => ( isa=>Int, default=>60, ); parameter part_max_lengths => ( isa=>Dict[ first=>Optional[Int], middle=>Optional[Int], last=>Optional[Int], ], ); my $Namepart = subtype { as Str; having isWords(maximum_words=>1), hasMinimumLength(2); parameter max_length => ( isa=>int, default=>20 ); parameterize($p Parameters) { having hasMaximumLength($p->max_length); } } parameterize($p Parameters) { as Dict[ first => $NamePart( max_length=>$p->part_max_lengths->{first}, ), middle => Optional[ $NamePart( max_length=>$p->part_max_lengths->{middle} ), ], last => $NamePart( max_length=>$p->part_max_lengths->{last}, ), ]; having hasMaximumLength($p->total_length); } } ## MyApp/MyClass/Foo.pm use MooseX::Declare; use MooseX::Types qw(EmailAddress); use MyApp::Types qw(FullName Name); Class Foo { with Class::DBIx::Role::Result => ( resultset_class => '', fields => { fullname => ..., name => ..., }, ); ## fullname would have a minimum of 2 characters, a maximum of 45 and ## would be composed of a maximum of 3 words separated by whitespace has fullname => ( is=>'rw', isa=>FullName(length=>45), ); ## name would be a HashRef with two required keys 'first' and 'last' ## and a single optional key called 'middle'. each key value must be a ## str composed of a single word with a minimum character length of 2 ## and maximum lengths of first=>35, middle=>25 and last=>50. Also the ## overall total length. has name => ( is=>'rw', isa=>Name( total_length=>95, part_max_lengths=>{ first=>35, middle=>25, last=>50, }, ), ); method email($recipient Email) { .... } } use aliased MyApp::MyClass::Foo; my $foo = Foo->new( fullname=>'Vanessa Li', name=>{ first=>'John', middle=>'James', last=>'Napiorkowski', }, ); my $foo_set = Foo->search( name => sub { $self->search ... }); ## COERCSIONS coercion fixPerson($person Person) { from Tuple($name Str, $age Int) { $person->XXXXX(name=>$name, age=>$age); } from Dict( :$fullname Fullname, :$dob DateTime ) { my $name = "$fullname->{first} $fullname->{last}"; my $age = ($dob - DateTime-now)->years; return $person->XXX(name=>$name, age=>$age); } } has 'attribute' => ( is=>'rw', isa=> Person->coercions(fixPerson, MorePeople), ); subtype myDelegate, as Delegate[Signature]; type Signature, as Optional[ Int, Pairs[ Pair[name=>Int], Pair[key=>Str], ],