Commit | Line | Data |
5964b3ca |
1 | package MooseX::Dependent; |
2 | |
3 | use 5.008; |
4 | |
5 | use strict; |
6 | use warnings; |
7 | |
8 | our $VERSION = '0.01'; |
9 | our $AUTHORITY = 'cpan:JJNAPIORK'; |
10 | |
11 | =head1 NAME |
12 | |
13 | MooseX::Dependent - Dependent L<MooseX::Types> constraints and L<Moose> attributes |
14 | |
15 | =head1 SYNOPSIS |
16 | |
17 | Given some L<MooseX::Types> declared as: |
18 | |
19 | package MyApp::Types; |
20 | |
21 | use MooseX::Types::Moose qw(Object, Int); |
22 | use MooseX::Dependent::Types qw(Dependent); |
23 | use Moosex::Types -declare => [qw(Set UniqueID)]; |
24 | |
25 | subtype Set, |
26 | as Object, |
27 | where { |
613e1e97 |
28 | shift->can('find'); |
5964b3ca |
29 | }; |
30 | |
31 | subtype UniqueID, |
32 | as Dependent[Int, Set], |
33 | where { |
613e1e97 |
34 | my ($int, $set) = @_; |
35 | return $set->find($int) ? 0:1; |
5964b3ca |
36 | }; |
37 | |
38 | Assuming 'Set' is a class that creates and manages sets of values (lists of |
39 | unique but unordered values) with a method '->find($n)', which returns true when |
40 | $n is a member of the set and which you instantiate like so: |
41 | |
613e1e97 |
42 | my $set_obj = Set->new(1,2,3,4,5); ## 1..5 are member of Set $set_obj' |
5964b3ca |
43 | |
44 | You can then use this $set_obj as a parameter on the previously declared type |
45 | constraint 'UniqueID'. This $set_obj become part of the constraint (you can't |
46 | actually use the constraint without it.) |
47 | |
613e1e97 |
48 | UniqueID[$set_obj]->check(1); ## Not OK, since one isn't unique in $set_obj |
49 | UniqueID[$set_obj]->check(100); ## OK, since 100 isn't in the set. |
50 | |
51 | You can assign the result of a parameterized dependent type to a variable or to |
52 | another type constraint, as like any other type constraint: |
53 | |
54 | ## As variable |
55 | my $unique = UniqueID[$set_obj]; |
56 | $unique->check(10); ## OK |
57 | $unique->check(2); ## Not OK, '2' is already in the set. |
58 | |
59 | ## As a new subtype |
60 | subtype UniqueInSet, as UniqueID[$set_obj]; |
61 | UniqueInSet->check(99); ## OK |
62 | UniqueInSet->check(3); ## Not OK, '3' is already in the set. |
63 | |
64 | However, you can't use a dependent type constraint to check or validate a value |
65 | until you've parameterized the dependent value: |
66 | |
67 | UniqueID->check(1000); ## Throws exception |
68 | UniqueID->validate(1000); ## Throws exception also |
69 | |
70 | This is a hard exception, rather than just returning a failure message (via the |
71 | validate method) or a false boolean (via the check method) since I consider an |
72 | unparameterized type constraint to be more than just an invalid condition. You |
73 | will have to catch these in an eval if you think you might have them. |
5964b3ca |
74 | |
613e1e97 |
75 | Afterward, you can use these dependent types on your L<Moose> based classes |
5964b3ca |
76 | and set the dependency target to the value of another attribute or method: |
77 | |
78 | TDB: Following is tentative |
79 | |
80 | package MyApp::MyClass; |
81 | |
82 | use Moose; |
83 | use MooseX::Dependent (or maybe a role, or traits...?) |
84 | use MooseX::Types::Moose qw(); |
85 | use MyApp::Types qw(UniqueID Set); |
86 | |
87 | has people => (is=>'ro', isa=>Set, required=>1); |
613e1e97 |
88 | has id => (is=>'ro', dependent_isa=>UniqueID, required=>1); |
5964b3ca |
89 | |
90 | Please see the test cases for more examples. |
91 | |
92 | =head1 DESCRIPTION |
93 | |
94 | A dependent type is a type constraint whose validity is dependent on a second |
95 | value. You defined the dependent type constraint with a primary type constraint |
96 | (such as 'Int') a 'constraining' value type constraint (such as a 'Set' object) |
97 | and a coderef (such as a 'where' clause in your type constraint declaration) |
98 | which will compare the incoming value to be checked with a value that conforms |
99 | to the constraining type constraint. |
100 | |
101 | Once created, you can use dependent types directly, or in your L<Moose> based |
102 | attributes and methods (if you are using L<MooseX::Declare>). Attribute traits |
103 | are available to make it easy to assign the dependency to the value of another |
104 | attribute or another method. |
105 | |
106 | =head1 TYPE CONSTRAINTS |
107 | |
108 | All type constraints are defined in L<MooseX::Dependent::Types>. Please see |
109 | that class for more documentation and examples of how to create type constraint |
110 | libraries using dependent types. |
111 | |
112 | =cut |
113 | |
114 | =head1 ATTRIBUTE TRAITS |
115 | |
116 | TBD |
117 | |
118 | =head1 SEE ALSO |
119 | |
120 | L<Moose>, L<Moose::Meta::TypeConstraints>, L<MooseX::Types> |
121 | |
122 | =head1 AUTHOR |
123 | |
124 | John Napiorkowski, C<< <jjnapiork@cpan.org> >> |
125 | |
126 | =head1 COPYRIGHT & LICENSE |
127 | |
128 | This program is free software; you can redistribute it and/or modify |
129 | it under the same terms as Perl itself. |
130 | |
131 | =cut |
132 | |
133 | 1; |