this speling test is really useful. fixed a whole bunch of types in the cookbook
[gitmo/Moose.git] / lib / Moose / Cookbook / Basics / Recipe4.pod
1
2 =pod
3
4 =head1 NAME
5
6 Moose::Cookbook::Basics::Recipe4 - Subtypes, and modeling a simple B<Company> class hierarchy
7
8 =head1 SYNOPSIS
9
10   package Address;
11   use Moose;
12   use Moose::Util::TypeConstraints;
13
14   use Locale::US;
15   use Regexp::Common 'zip';
16
17   my $STATES = Locale::US->new;
18   subtype 'USState'
19       => as Str
20       => where {
21              (    exists $STATES->{code2state}{ uc($_) }
22                || exists $STATES->{state2code}{ uc($_) } );
23          };
24
25   subtype 'USZipCode'
26       => as Value
27       => where {
28              /^$RE{zip}{US}{-extended => 'allow'}$/;
29          };
30
31   has 'street'   => ( is => 'rw', isa => 'Str' );
32   has 'city'     => ( is => 'rw', isa => 'Str' );
33   has 'state'    => ( is => 'rw', isa => 'USState' );
34   has 'zip_code' => ( is => 'rw', isa => 'USZipCode' );
35
36   package Company;
37   use Moose;
38   use Moose::Util::TypeConstraints;
39
40   has 'name' => ( is => 'rw', isa => 'Str', required => 1 );
41   has 'address'   => ( is => 'rw', isa => 'Address' );
42   has 'employees' => ( is => 'rw', isa => 'ArrayRef[Employee]' );
43
44   sub BUILD {
45       my ( $self, $params ) = @_;
46       if ( @{ $self->employees } ) {
47           foreach my $employee ( @{ $self->employees } ) {
48               $employee->company($self);
49           }
50       }
51   }
52
53   after 'employees' => sub {
54       my ( $self, $employees ) = @_;
55       if ($employees) {
56           foreach my $employee ( @{$employees} ) {
57               $employee->company($self);
58           }
59       }
60   };
61
62   package Person;
63   use Moose;
64
65   has 'first_name' => ( is => 'rw', isa => 'Str', required => 1 );
66   has 'last_name'  => ( is => 'rw', isa => 'Str', required => 1 );
67   has 'middle_initial' => (
68       is        => 'rw', isa => 'Str',
69       predicate => 'has_middle_initial'
70   );
71   has 'address' => ( is => 'rw', isa => 'Address' );
72
73   sub full_name {
74       my $self = shift;
75       return $self->first_name
76           . (
77           $self->has_middle_initial
78           ? ' ' . $self->middle_initial . '. '
79           : ' '
80           ) . $self->last_name;
81   }
82
83   package Employee;
84   use Moose;
85
86   extends 'Person';
87
88   has 'title'    => ( is => 'rw', isa => 'Str',     required => 1 );
89   has 'employer' => ( is => 'rw', isa => 'Company', weak_ref => 1 );
90
91   override 'full_name' => sub {
92       my $self = shift;
93       super() . ', ' . $self->title;
94   };
95
96 =head1 DESCRIPTION
97
98 This recipe introduces the C<subtype> sugar function from
99 L<Moose::Util::TypeConstraints>. The C<subtype> function lets you
100 declaratively create type constraints without building an entire
101 class.
102
103 In the recipe we also make use of L<Locale::US> and L<Regexp::Common>
104 to build constraints, showing how how constraints can make use of
105 existing CPAN tools for data validation.
106
107 Finally, we introduce the C<required> attribute parameter.
108
109 The the C<Address> class we define two subtypes. The first uses the
110 L<Locale::US> module to check the validity of a state. It accepts
111 either a state abbreviation of full name.
112
113 A state will be passed in as a string, so we make our C<USState> type
114 a subtype of Moose's builtin C<Str> type. This is done using the C<as>
115 sugar. The actual constraint is defined using C<where>. This function
116 accepts a single subroutine reference. That subroutine will be called
117 with the value to be checked in C<$_> (1). It is expected to return a
118 true or false value indicating whether the value is valid for the
119 type.
120
121 We can now use the C<USState> type just like Moose's builtin types:
122
123   has 'state'    => ( is => 'rw', isa => 'USState' );
124
125 When the C<state> attribute is set, the value is checked against the
126 C<USState> constraint. If the value is not valid, an exception will be
127 thrown.
128
129 The next C<subtype>, C<USZipCode>, uses
130 L<Regexp::Common>. L<Regexp::Common> includes a regex for validating
131 US zip codes. We use this constraint for the C<zip_code> attribute.
132
133   subtype 'USZipCode'
134       => as Value
135       => where {
136              /^$RE{zip}{US}{-extended => 'allow'}$/;
137          };
138
139 Using a subtype instead of requiring a class for each type greatly
140 simplifies the code. We don't really need a class for these types, as
141 they're just strings, but we do want to ensure that they're valid.
142
143 The type constraints we created are reusable. Type constraints are
144 stored by name in a global registry. This means that we can refer to
145 them in other classes. Because the registry is global, we do recommend
146 that you use some sort of pseudo-namespacing in real applications,
147 like C<MyApp.Type.USState>.
148
149 These two subtypes allow us to define a simple C<Address> class.
150
151 Then we define our C<Company> class, which has an address. As we saw
152 in earlier recipes, Moose automatically creates a type constraint for
153 each our classes, so we can use that for the C<Company> class's
154 C<address> attribute:
155
156   has 'address'   => ( is => 'rw', isa => 'Address' );
157
158 A company also needs a name:
159
160   has 'name' => ( is => 'rw', isa => 'Str', required => 1 );
161
162 This introduces a new attribute parameter, C<required>. If an
163 attribute is required, then it must be passed to the class's
164 constructor, or an exception will be thrown. It's important to
165 understand that a C<required> attribute can still be false or
166 C<undef>, if its type constraint allows that.
167
168 The next attribute, C<employees>, uses a I<parameterized> type
169 constraint:
170
171   has 'employees' => ( is => 'rw', isa => 'ArrayRef[Employee]' );
172
173 This constraint says that C<employees> must be an array reference
174 where each element of the array is an C<Employee> object. It's worth
175 noting that an I<empty> array reference also satisfies this
176 constraint.
177
178 Parameterizable type constraints (or "container types), such as
179 C<ArrayRef[`a]>, can be made more specific with a type parameter. In
180 fact, we can arbitrarily nest these types, producing something like
181 C<HashRef[ArrayRef[Int]]>. However, you can also just use the type by
182 itself, so C<ArrayRef> is legal. (2)
183
184 If you jump down to the definition of the C<Employee> class, you will
185 see that it has an C<employer> attribute.
186
187 When we set the C<employees> for a C<Company> we want to make sure
188 that each of these employee objects refers back to the right
189 C<Company> in its C<employer> attribute.
190
191 To do that, we need to hook into object construction. Moose lets us do
192 this by writing a C<BUILD> method in our class. When your class
193 defined a C<BUILD> method, it will be called immediately after an
194 object construction, but before the object is returned to the caller
195 (3).
196
197 The C<Company> class uses the C<BUILD> method to ensure that each
198 employee of a company has the proper C<Company> object in its
199 C<employer> attribute:
200
201   sub BUILD {
202       my ( $self, $params ) = @_;
203       if ( $self->employees ) {
204           foreach my $employee ( @{ $self->employees } ) {
205               $employee->company($self);
206           }
207       }
208   }
209
210 The C<BUILD> method is executed after type constraints are checked, so
211 it is safe to assume that C<< $self->employees >> will return an array
212 reference, and that the elements of that array will be C<Employee>
213 objects.
214
215 We also want to make sure that whenever the C<employees> attribute for
216 a C<Company> is changed, we also update the C<employer> for each
217 employee.
218
219 To do this we can use an C<after> modifier:
220
221   after 'employees' => sub {
222       my ( $self, $employees ) = @_;
223       if ($employees) {
224           foreach my $employee ( @{$employees} ) {
225               $employee->company($self);
226           }
227       }
228   };
229
230 Again, as with the C<BUILD> method, we know that the type constraint
231 check has already happened, so we can just check for definedness on the
232 C<$employees> argument.
233
234 The B<Person> class does have demonstrate anything new. It has several
235 C<required> attributes. It also has a C<predicate> method, which we
236 first used in L<recipe 3|Moose::Cookbook::Basics::Recipe3>.
237
238 The only new feature in the C<Employee> class is the C<override>
239 method modifier:
240
241   override 'full_name' => sub {
242       my $self = shift;
243       super() . ', ' . $self->title;
244   };
245
246 This is just a sugary alternative to Perl's built in C<SUPER::>
247 feature. However, there is one difference. You cannot pass any
248 arguments to C<super>. Instead, Moose simply passes the same
249 parameters that were passed to the method.
250
251 A more detailed example of usage can be found in
252 F<t/000_recipes/004_recipe.t>.
253
254 =head1 CONCLUSION
255
256 This recipe was intentionally longer and more complex. It illustrates
257 how Moose classes can be used together with type constraints, as well
258 as the density of information that you can get out of a small amount
259 of typing when using Moose.
260
261 This recipe also introduced the C<subtype> function, the C<required>
262 attribute, and the C<override> method modifier.
263
264 We will revisit type constraints in future recipes, and cover type
265 coercion as well.
266
267 =head1 FOOTNOTES
268
269 =over 4
270
271 =item (1)
272
273 The value being checked is also passed as the first argument to
274 the C<where> block, so it can be accessed as C<$_[0]>.
275
276 =item (2)
277
278 Note that C<ArrayRef[]> will not work. Moose will not parse this as a
279 container type, and instead you will have a new type named
280 "ArrayRef[]", which doesn't make any sense.
281
282 =item (3)
283
284 The C<BUILD> method is actually called by C<< Moose::Object->BUILDALL
285 >>, which is called by C<< Moose::Object->new >>. The C<BUILDALL>
286 method climbs the object inheritance graph and calls any C<BUILD>
287 methods it finds in the correct order.
288
289 =back
290
291 =head1 AUTHORS
292
293 Stevan Little E<lt>stevan@iinteractive.comE<gt>
294
295 Dave Rolsky E<lt>autarch@urth.orgE<gt>
296
297 =head1 COPYRIGHT AND LICENSE
298
299 Copyright 2006-2009 by Infinity Interactive, Inc.
300
301 L<http://www.iinteractive.com>
302
303 This library is free software; you can redistribute it and/or modify
304 it under the same terms as Perl itself.
305
306 =cut