9ab310e744fb961584a677625b44edb20e9a5ca1
[gitmo/MooseX-Dependent.git] / lib / MooseX / Dependent.pm
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 {
28                     shift->can('find');
29                 };
30
31         subtype UniqueID,
32                 as Dependent[Int, Set],
33                 where {
34                     my ($int, $set) = @_;
35                     return $set->find($int) ? 0:1;
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
42     my $set_obj = Set->new(1,2,3,4,5); ## 1..5 are member of Set $set_obj'
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
48     UniqueID([$set_obj])->check(1); ## Not OK, since one isn't unique in $set_obj
49     UniqueID([$set_obj])->check('AAA'); ## Not OK, since AAA is not an Int
50     UniqueID([$set_obj])->check(100); ## OK, since 100 isn't in the set.
51     
52 You can assign the result of a parameterized dependent type to a variable or to
53 another type constraint, as like any other type constraint:
54
55     ## As variable
56     my $unique = UniqueID[$set_obj];
57     $unique->check(10); ## OK
58     $unique->check(2); ## Not OK, '2' is already in the set.
59     
60     ## As a new subtype
61     subtype UniqueInSet, as UniqueID[$set_obj];
62     UniqueInSet->check(99); ## OK
63     UniqueInSet->check(3); ## Not OK, '3' is already in the set.
64     
65 However, you can't use a dependent type constraint to check or validate a value
66 until you've parameterized the dependent value:
67
68     UniqueID->check(1000); ## Throws exception
69     UniqueID->validate(1000); ## Throws exception also
70     
71 This is a hard exception, rather than just returning a failure message (via the
72 validate method) or a false boolean (via the check method) since I consider an
73 unparameterized type constraint to be more than just an invalid condition.  You
74 will have to catch these in an eval if you think you might have them.
75
76 Afterward, you can use these dependent types on your L<Moose> based classes
77 and set the dependency target to the value of another attribute or method:
78
79     TDB: Following is tentative
80     
81     package MyApp::MyClass;
82
83     use Moose;
84     use MooseX::Dependent (or maybe a role, or traits...?)
85     use MooseX::Types::Moose qw();
86     use MyApp::Types qw(UniqueID Set);
87     
88     has people => (is=>'ro', isa=>Set, required=>1);
89     has id => (is=>'ro', dependent_isa=>UniqueID, required=>1);
90
91 Please see the test cases for more examples.
92
93 =head1 DESCRIPTION
94
95 A dependent type is a type constraint whose validity is dependent on a second
96 value.  You defined the dependent type constraint with a primary type constraint
97 (such as 'Int') a 'constraining' value type constraint (such as a 'Set' object)
98 and a coderef (such as a 'where' clause in your type constraint declaration)
99 which will compare the incoming value to be checked with a value that conforms
100 to the constraining type constraint.
101
102 Once created, you can use dependent types directly, or in your L<Moose> based
103 attributes and methods (if you are using L<MooseX::Declare>).  Attribute traits
104 are available to make it easy to assign the dependency to the value of another
105 attribute or another method.
106
107 =head1 TYPE CONSTRAINTS
108
109 All type constraints are defined in L<MooseX::Dependent::Types>.  Please see
110 that class for more documentation and examples of how to create type constraint
111 libraries using dependent types.
112
113 =cut
114
115 =head1 ATTRIBUTE TRAITS
116
117     TBD
118
119 =head1 SEE ALSO
120
121 L<Moose>, L<Moose::Meta::TypeConstraints>, L<MooseX::Types>
122
123 =head1 AUTHOR
124
125 John Napiorkowski, C<< <jjnapiork@cpan.org> >>
126
127 =head1 COPYRIGHT & LICENSE
128
129 This program is free software; you can redistribute it and/or modify
130 it under the same terms as Perl itself.
131
132 =cut
133
134 1;