Add built local::lib
[catagits/Gitalist.git] / local-lib5 / man / man3 / Moose::Cookbook::Basics::Recipe5.3pm
1 .\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.3
2 .\"
3 .\" Standard preamble:
4 .\" ========================================================================
5 .de Sh \" Subsection heading
6 .br
7 .if t .Sp
8 .ne 5
9 .PP
10 \fB\\$1\fR
11 .PP
12 ..
13 .de Sp \" Vertical space (when we can't use .PP)
14 .if t .sp .5v
15 .if n .sp
16 ..
17 .de Vb \" Begin verbatim text
18 .ft CW
19 .nf
20 .ne \\$1
21 ..
22 .de Ve \" End verbatim text
23 .ft R
24 .fi
25 ..
26 .\" Set up some character translations and predefined strings.  \*(-- will
27 .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
28 .\" double quote, and \*(R" will give a right double quote.  | will give a
29 .\" real vertical bar.  \*(C+ will give a nicer C++.  Capital omega is used to
30 .\" do unbreakable dashes and therefore won't be available.  \*(C` and \*(C'
31 .\" expand to `' in nroff, nothing in troff, for use with C<>.
32 .tr \(*W-|\(bv\*(Tr
33 .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
34 .ie n \{\
35 .    ds -- \(*W-
36 .    ds PI pi
37 .    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
38 .    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
39 .    ds L" ""
40 .    ds R" ""
41 .    ds C` ""
42 .    ds C' ""
43 'br\}
44 .el\{\
45 .    ds -- \|\(em\|
46 .    ds PI \(*p
47 .    ds L" ``
48 .    ds R" ''
49 'br\}
50 .\"
51 .\" If the F register is turned on, we'll generate index entries on stderr for
52 .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
53 .\" entries marked with X<> in POD.  Of course, you'll have to process the
54 .\" output yourself in some meaningful fashion.
55 .if \nF \{\
56 .    de IX
57 .    tm Index:\\$1\t\\n%\t"\\$2"
58 ..
59 .    nr % 0
60 .    rr F
61 .\}
62 .\"
63 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
64 .\" way too many mistakes in technical documents.
65 .hy 0
66 .if n .na
67 .\"
68 .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
69 .\" Fear.  Run.  Save yourself.  No user-serviceable parts.
70 .    \" fudge factors for nroff and troff
71 .if n \{\
72 .    ds #H 0
73 .    ds #V .8m
74 .    ds #F .3m
75 .    ds #[ \f1
76 .    ds #] \fP
77 .\}
78 .if t \{\
79 .    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
80 .    ds #V .6m
81 .    ds #F 0
82 .    ds #[ \&
83 .    ds #] \&
84 .\}
85 .    \" simple accents for nroff and troff
86 .if n \{\
87 .    ds ' \&
88 .    ds ` \&
89 .    ds ^ \&
90 .    ds , \&
91 .    ds ~ ~
92 .    ds /
93 .\}
94 .if t \{\
95 .    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
96 .    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
97 .    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
98 .    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
99 .    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
100 .    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
101 .\}
102 .    \" troff and (daisy-wheel) nroff accents
103 .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
104 .ds 8 \h'\*(#H'\(*b\h'-\*(#H'
105 .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
106 .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
107 .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
108 .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
109 .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
110 .ds ae a\h'-(\w'a'u*4/10)'e
111 .ds Ae A\h'-(\w'A'u*4/10)'E
112 .    \" corrections for vroff
113 .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
114 .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
115 .    \" for low resolution devices (crt and lpr)
116 .if \n(.H>23 .if \n(.V>19 \
117 \{\
118 .    ds : e
119 .    ds 8 ss
120 .    ds o a
121 .    ds d- d\h'-1'\(ga
122 .    ds D- D\h'-1'\(hy
123 .    ds th \o'bp'
124 .    ds Th \o'LP'
125 .    ds ae ae
126 .    ds Ae AE
127 .\}
128 .rm #[ #] #H #V #F C
129 .\" ========================================================================
130 .\"
131 .IX Title "Moose::Cookbook::Basics::Recipe5 3"
132 .TH Moose::Cookbook::Basics::Recipe5 3 "2009-03-14" "perl v5.8.7" "User Contributed Perl Documentation"
133 .SH "NAME"
134 Moose::Cookbook::Basics::Recipe5 \- More subtypes, coercion in a \fBRequest\fR class
135 .SH "SYNOPSIS"
136 .IX Header "SYNOPSIS"
137 .Vb 3
138 \&  package Request;
139 \&  use Moose;
140 \&  use Moose::Util::TypeConstraints;
141 .Ve
142 .PP
143 .Vb 3
144 \&  use HTTP::Headers  ();
145 \&  use Params::Coerce ();
146 \&  use URI            ();
147 .Ve
148 .PP
149 .Vb 1
150 \&  subtype 'My::Types::HTTP::Headers' => as class_type('HTTP::Headers');
151 .Ve
152 .PP
153 .Vb 5
154 \&  coerce 'My::Types::HTTP::Headers'
155 \&      => from 'ArrayRef'
156 \&          => via { HTTP::Headers\->new( @{$_} ) }
157 \&      => from 'HashRef'
158 \&          => via { HTTP::Headers\->new( %{$_} ) };
159 .Ve
160 .PP
161 .Vb 1
162 \&  subtype 'My::Types::URI' => as class_type('URI');
163 .Ve
164 .PP
165 .Vb 7
166 \&  coerce 'My::Types::URI'
167 \&      => from 'Object'
168 \&          => via { $_\->isa('URI')
169 \&                   ? $_
170 \&                   : Params::Coerce::coerce( 'URI', $_ ); }
171 \&      => from 'Str'
172 \&          => via { URI\->new( $_, 'http' ) };
173 .Ve
174 .PP
175 .Vb 3
176 \&  subtype 'Protocol'
177 \&      => as 'Str'
178 \&      => where { /^HTTP\e/[0\-9]\e.[0\-9]$/ };
179 .Ve
180 .PP
181 .Vb 10
182 \&  has 'base' => ( is => 'rw', isa => 'My::Types::URI', coerce => 1 );
183 \&  has 'uri'  => ( is => 'rw', isa => 'My::Types::URI', coerce => 1 );
184 \&  has 'method'   => ( is => 'rw', isa => 'Str' );
185 \&  has 'protocol' => ( is => 'rw', isa => 'Protocol' );
186 \&  has 'headers'  => (
187 \&      is      => 'rw',
188 \&      isa     => 'My::Types::HTTP::Headers',
189 \&      coerce  => 1,
190 \&      default => sub { HTTP::Headers\->new }
191 \&  );
192 .Ve
193 .SH "DESCRIPTION"
194 .IX Header "DESCRIPTION"
195 This recipe introduces type coercions, which are defined with the
196 \&\f(CW\*(C`coerce\*(C'\fR sugar function. Coercions are attached to existing type
197 constraints, and define a (one\-way) transformation from one type to
198 another.
199 .PP
200 This is very powerful, but it's also magical, so you have to
201 explicitly ask for an attribute to be coerced. To do this, you must
202 set the \f(CW\*(C`coerce\*(C'\fR attribute option to a true value.
203 .PP
204 First, we create the subtype to which we will coerce the other types:
205 .PP
206 .Vb 1
207 \&  subtype 'My::Types::HTTP::Headers' => as class_type('HTTP::Headers');
208 .Ve
209 .PP
210 We are creating a subtype rather than using \f(CW\*(C`HTTP::Headers\*(C'\fR as a type
211 directly. The reason we do this is coercions are global, and a
212 coercion defined for \f(CW\*(C`HTTP::Headers\*(C'\fR in our \f(CW\*(C`Request\*(C'\fR class would
213 then be defined for \fIall\fR Moose-using classes in the current Perl
214 interpreter. It's a best practice to
215 avoid this sort of namespace pollution.
216 .PP
217 The \f(CW\*(C`class_type\*(C'\fR sugar function is simply a shortcut for this:
218 .PP
219 .Vb 3
220 \&  subtype 'HTTP::Headers'
221 \&      => as 'Object'
222 \&      => where { $_\->isa('HTTP::Headers') };
223 .Ve
224 .PP
225 Internally, Moose creates a type constraint for each Moose-using
226 class, but for non-Moose classes, the type must be declared
227 explicitly.
228 .PP
229 We could go ahead and use this new type directly:
230 .PP
231 .Vb 5
232 \&  has 'headers' => (
233 \&      is      => 'rw',
234 \&      isa     => 'HTTP::Headers',
235 \&      default => sub { HTTP::Headers\->new }
236 \&  );
237 .Ve
238 .PP
239 This creates a simple attribute which defaults to an empty instance of
240 HTTP::Headers.
241 .PP
242 The constructor for HTTP::Headers accepts a list of key-value pairs
243 representing the \s-1HTTP\s0 header fields. In Perl, such a list could be
244 stored in an \s-1ARRAY\s0 or \s-1HASH\s0 reference. We want our \f(CW\*(C`headers\*(C'\fR attribute
245 to accept those data structure instead of an \fBHTTP::Headers\fR
246 instance, and just do the right thing. This is exactly what coercion
247 is for:
248 .PP
249 .Vb 5
250 \&  coerce 'My::Types::HTTP::Headers'
251 \&      => from 'ArrayRef'
252 \&          => via { HTTP::Headers\->new( @{$_} ) }
253 \&      => from 'HashRef'
254 \&          => via { HTTP::Headers\->new( %{$_} ) };
255 .Ve
256 .PP
257 The first argument to \f(CW\*(C`coerce\*(C'\fR is the type \fIto\fR which we are
258 coercing. Then we give it a set of \f(CW\*(C`from\*(C'\fR/\f(CW\*(C`via\*(C'\fR clauses. The \f(CW\*(C`from\*(C'\fR
259 function takes some other type name and \f(CW\*(C`via\*(C'\fR takes a subroutine
260 reference which actually does the coercion.
261 .PP
262 However, defining the coercion doesn't do anything until we tell Moose
263 we want a particular attribute to be coerced:
264 .PP
265 .Vb 6
266 \&  has 'headers' => (
267 \&      is      => 'rw',
268 \&      isa     => 'My::Types::HTTP::Headers',
269 \&      coerce  => 1,
270 \&      default => sub { HTTP::Headers\->new }
271 \&  );
272 .Ve
273 .PP
274 Now, if we use an \f(CW\*(C`ArrayRef\*(C'\fR or \f(CW\*(C`HashRef\*(C'\fR to populate \f(CW\*(C`headers\*(C'\fR, it
275 will be coerced into a new HTTP::Headers instance. With the
276 coercion in place, the following lines of code are all equivalent:
277 .PP
278 .Vb 3
279 \&  $foo\->headers( HTTP::Headers\->new( bar => 1, baz => 2 ) );
280 \&  $foo\->headers( [ 'bar', 1, 'baz', 2 ] );
281 \&  $foo\->headers( { bar => 1, baz => 2 } );
282 .Ve
283 .PP
284 As you can see, careful use of coercions can produce a very open
285 interface for your class, while still retaining the \*(L"safety\*(R" of your
286 type constraint checks. (1)
287 .PP
288 Our next coercion shows how we can leverage existing \s-1CPAN\s0 modules to
289 help implement coercions. In this case we use Params::Coerce.
290 .PP
291 Once again, we need to declare a class type for our non-Moose \s-1URI\s0
292 class:
293 .PP
294 .Vb 1
295 \&  subtype 'My::Types::URI' => as class_type('URI');
296 .Ve
297 .PP
298 Then we define the coercion:
299 .PP
300 .Vb 7
301 \&  coerce 'My::Types::URI'
302 \&      => from 'Object'
303 \&          => via { $_\->isa('URI')
304 \&                   ? $_
305 \&                   : Params::Coerce::coerce( 'URI', $_ ); }
306 \&      => from 'Str'
307 \&          => via { URI\->new( $_, 'http' ) };
308 .Ve
309 .PP
310 The first coercion takes any object and makes it a \f(CW\*(C`URI\*(C'\fR object. The
311 coercion system isn't that smart, and does not check if the object is
312 already a \s-1URI\s0, so we check for that ourselves. If it's not a \s-1URI\s0
313 already, we let Params::Coerce do its magic, and we just use its
314 return value.
315 .PP
316 If Params::Coerce didn't return a \s-1URI\s0 object (for whatever
317 reason), Moose would throw a type constraint error.
318 .PP
319 The other coercion takes a string and converts to a \s-1URI\s0. In this
320 case, we are using the coercion to apply a default behavior, where a
321 string is assumed to be an \f(CW\*(C`http\*(C'\fR \s-1URI\s0.
322 .PP
323 Finally, we need to make sure our attributes enable coercion.
324 .PP
325 .Vb 2
326 \&  has 'base' => ( is => 'rw', isa => 'My::Types::URI', coerce => 1 );
327 \&  has 'uri'  => ( is => 'rw', isa => 'My::Types::URI', coerce => 1 );
328 .Ve
329 .PP
330 Re-using the coercion lets us enforce a consistent \s-1API\s0 across multiple
331 attributes.
332 .SH "CONCLUSION"
333 .IX Header "CONCLUSION"
334 This recipe showed the use of coercions to create a more flexible and
335 DWIM-y \s-1API\s0. Like any powerful magic, we recommend some
336 caution. Sometimes it's better to reject a value than just guess at
337 how to \s-1DWIM\s0.
338 .PP
339 We also showed the use of the \f(CW\*(C`class_type\*(C'\fR sugar function as a
340 shortcut for defining a new subtype of \f(CW\*(C`Object\*(C'\fR
341 .SH "FOOTNOTES"
342 .IX Header "FOOTNOTES"
343 .IP "(1)" 4
344 .IX Item "(1)"
345 This particular example could be safer. Really we only want to coerce
346 an array with an \fIeven\fR number of elements. We could create a new
347 \&\f(CW\*(C`EvenElementArrayRef\*(C'\fR type, and then coerce from that type, as
348 opposed to from a plain \f(CW\*(C`ArrayRef\*(C'\fR
349 .SH "AUTHORS"
350 .IX Header "AUTHORS"
351 Stevan Little <stevan@iinteractive.com>
352 .PP
353 Dave Rolsky <autarch@urth.org>
354 .SH "COPYRIGHT AND LICENSE"
355 .IX Header "COPYRIGHT AND LICENSE"
356 Copyright 2006\-2009 by Infinity Interactive, Inc.
357 .PP
358 <http://www.iinteractive.com>
359 .PP
360 This library is free software; you can redistribute it and/or modify
361 it under the same terms as Perl itself.