X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMooseX%2FDependent.pm;h=a3f4c5db5ec5ab201ff4e9c7dcf79d8c238b2568;hb=91623f94185ece8f2c6f2716dca9e6f7c1158963;hp=6c8b293a7814127ff71a5dd81b148e37b42de6e3;hpb=5964b3cacce00a1797717802e007fbb7cadc95fb;p=gitmo%2FMooseX-Dependent.git diff --git a/lib/MooseX/Dependent.pm b/lib/MooseX/Dependent.pm index 6c8b293..a3f4c5d 100644 --- a/lib/MooseX/Dependent.pm +++ b/lib/MooseX/Dependent.pm @@ -20,35 +20,59 @@ Given some L declared as: use MooseX::Types::Moose qw(Object, Int); use MooseX::Dependent::Types qw(Dependent); - use Moosex::Types -declare => [qw(Set UniqueID)]; + use Moosex::Types -declare => [qw(Set UniqueInt)]; + + use Set::Scalar; subtype Set, - as Object, - where { - shift->can('find'); - }; + as class_type("Set::Scalar"); - subtype UniqueID, + subtype UniqueInt, as Dependent[Int, Set], where { - my ($int, $set) = @_; - return $set->find($int) ? 0:1; + my ($int, $set) = @_; + return !$set->has($int) ; }; Assuming 'Set' is a class that creates and manages sets of values (lists of -unique but unordered values) with a method '->find($n)', which returns true when +unique but unordered values) with a method '->has($n)', which returns true when $n is a member of the set and which you instantiate like so: - my $set_obj = Set->new(1,2,3,4,5); ## 1..5 are member of Set $set_obj' + my $set_obj = Set->new(1,2,3,4,5); ## 1..5 are member of Set $set_obj' You can then use this $set_obj as a parameter on the previously declared type -constraint 'UniqueID'. This $set_obj become part of the constraint (you can't +constraint 'UniqueInt'. This $set_obj become part of the constraint (you can't actually use the constraint without it.) - UniqueID[$set_obj]->check(1); ## Not OK, since one isn't unique in $set_obj - UniqueID[$set_obj]->check(100); ## OK, since 100 isn't in the set. + UniqueInt([$set_obj])->check(1); ## Not OK, since one isn't unique in $set_obj + UniqueInt([$set_obj])->check('AAA'); ## Not OK, since AAA is not an Int + UniqueInt([$set_obj])->check(100); ## OK, since 100 isn't in the set. + +You can assign the result of a parameterized dependent type to a variable or to +another type constraint, as like any other type constraint: + + ## As variable + my $unique = UniqueInt[$set_obj]; + $unique->check(10); ## OK + $unique->check(2); ## Not OK, '2' is already in the set. + + ## As a new subtype + subtype UniqueInSet, as UniqueInt[$set_obj]; + UniqueInSet->check(99); ## OK + UniqueInSet->check(3); ## Not OK, '3' is already in the set. + +However, you can't use a dependent type constraint to check or validate a value +until you've parameterized the dependent value: + + UniqueInt->check(1000); ## Throws exception + UniqueInt->validate(1000); ## Throws exception also + +This is a hard exception, rather than just returning a failure message (via the +validate method) or a false boolean (via the check method) since I consider an +unparameterized type constraint to be more than just an invalid condition. You +will have to catch these in an eval if you think you might have them. -Additionally, you can use these dependent types on your L based classes +Afterward, you can use these dependent types on your L based classes and set the dependency target to the value of another attribute or method: TDB: Following is tentative @@ -58,10 +82,12 @@ and set the dependency target to the value of another attribute or method: use Moose; use MooseX::Dependent (or maybe a role, or traits...?) use MooseX::Types::Moose qw(); - use MyApp::Types qw(UniqueID Set); + use MyApp::Types qw(UniqueInt Set); has people => (is=>'ro', isa=>Set, required=>1); - has id => (is=>'ro', isa=>UniqueID, required=>1); + has id => (is=>'ro', dependent_isa=>UniqueInt, required=>1); + + TODO notes, coerce=>1 should coerce both check value and constraining value Please see the test cases for more examples. @@ -79,6 +105,11 @@ attributes and methods (if you are using L). Attribute traits are available to make it easy to assign the dependency to the value of another attribute or another method. +A Dependent Type Constraint should be a 'drop in' replacement for any place you +need the parent type (the type constraint being made dependent). For example, +if you are expecting an 'Int' type, you can use the 'UniqueInt' type constraint +as described above, since a UniqueInt is considered a subtype of Int. + =head1 TYPE CONSTRAINTS All type constraints are defined in L. Please see @@ -101,6 +132,8 @@ John Napiorkowski, C<< >> =head1 COPYRIGHT & LICENSE +Copyright 2008-2009, John Napiorkowski C<< >> + This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.