]> git.decadent.org.uk Git - maypole.git/blob - lib/Maypole/Manual/StandardTemplates.pod
35f9a8a86cca5befa0347d1808cc4a4643727af6
[maypole.git] / lib / Maypole / Manual / StandardTemplates.pod
1
2 =head1 Maypole's Standard Templates and Actions
3
4 As we saw in our Create-Read-Update-Delete (CRUD) example,
5 Maypole does all it can to make your life
6 easier; this inclues providing a set of default actions and
7 factory-supplied templates. These are written in such a generic way,
8 making extensive use of class metadata, that they are more or less
9 applicable to any table or application. However, in order to progress
10 from automatically generated CRUD applications to real customized
11 applications, we need to begin by understanding how these default
12 actions do their stuff, and how the default templates are put together.
13 Once we have an understanding of what Maypole does for us automatically,
14 we can begin to customize and create our own templates and actions.
15
16 Although the standard templates can be applied in many situations,
17 they're really provided just as examples,
18 as a starting point to create your own templates to suit your needs.
19 The goal of templating is to keep templates simple so the presentation
20 can be changed easily when you desire.
21 We're not trying to build a single set of reusable templates that cover
22 every possible situation.
23
24 =head2 The standard actions
25
26 Remember that actions are just subroutines in the model classes with an
27 I<Exported> attribute.
28 A simple, uncustomized Maypole model class, such as one of the classes
29 in the beer database application, provides the following default actions
30 - that is, provides access to the following URLs:
31
32 =over 3
33
34 =item C</[table]/view/[id]>
35
36 This takes the ID of an object in a table, retrieves the object, and
37 presents it to the F<view> template.
38
39 =item C</[table]/edit/[id]>
40
41 This is the same as C<view>, but uses the F<edit> template to provide a
42 web form to edit the object; it submits to C<do_edit>.
43
44 =item C</[table]/do_edit/[id]>
45
46 When called with an ID, the C<do_edit> action provides row editing.
47
48 =item C</[table]/do_edit/>
49
50 When called without an ID, the C<do_edit> action provides row creation.
51
52 =item C</[table]/delete/id>
53
54 This deletes a row, returning to the C<list> page.
55
56 =item C</[table]/list/>
57
58 This provides a paged list of the table suitable for browsing.
59
60 =item C</[table]/search/>
61
62 This handles a search query and presents the search results back to the
63 F<list> template.
64
65 =back
66
67 We'll now look at how these actions are implemented, before moving on to
68 take a detailed look at the templates they drive.
69
70 =head3 C<view> and C<edit>
71
72 These actions are very simple; their job is to take a row ID, turn it
73 into an object, and hand it to the template to be displayed. However, as
74 taking the first argument and turning it into an object is such a common
75 action, it is handled directly by the model class's C<process> method.
76 Similarly, the default template name provided by the C<process> method
77 is the name of the action, and so will be C<view> or C<edit>
78 accordingly. 
79
80 So the code required to make these two actions work turns out to be:
81
82     sub view :Exported { }
83     sub edit :Exported { }
84
85 That's right - no code at all. This shows the power of the templating
86 side of the system. If you think about it for a moment, it is natural
87 that these actions should not have any code - after all, we have
88 separated out the concerns of "acting" and displaying. Both of these
89 "actions" are purely concerned with displaying a record, and don't need
90 to do any "acting". Remember that the "edit" method doesn't actually do
91 any editing - this is provided by C<do_edit>; it is just another view of
92 the data, albeit one which allows the data to be modified later. These
93 two methods don't need to modify the row in any way, they don't need to
94 do anything clever. They just are.
95
96 So why do we need the subroutines at all? If the subroutines did not exist,
97 we would be sent to the C<view> and C<edit> templates as would be
98 expected, but these templates would not be provided with the right
99 arguments; we need to go through the C<process> method in order to turn
100 the URL argument into a row and thence into an object to be fed to the
101 template. By exporting these methods, even though they contain no code
102 themselves, we force Maypole to call C<process> and provide the class
103 and object to the templates.
104
105 The moral of this story is that if you need to have an action which is
106 purely concerned with display, not acting, but needs to receive an ID
107 and turn it into an object, then create an empty method. For instance,
108 if we want to make an alternate view of a row which only showed the
109 important columns, we might create a method
110
111     sub short_view :Exported {}
112
113 This will cause the row to be turned into an object and fed to the
114 C<short_view> template, and that template would be responsible for
115 selecting the particular columns to be displayed.
116
117 =head3 C<do_edit>
118
119 This action, on the other hand, actually has to do something. If it's
120 provided with an ID, this is turned into an object and we're in edit
121 mode, acting upon that object. If not, we're in create mode. 
122
123     sub do_edit :Exported {
124         my ($self, $r) = @_;
125         my $h = CGI::Untaint->new(%{$r->params});
126         my ($obj) = @{$r->objects || []};
127         if ($obj) {
128             # We have something to edit
129             $obj->update_from_cgi($h);
130         } else {
131             $obj = $self->create_from_cgi($h);
132         }
133
134 The C<CDBI> model uses the C<update_from_cgi> and C<create_from_cgi>
135 methods of L<Class::DBI::FromCGI> to turn C<POST> parameters
136 into database table data. This in turn uses L<CGI::Untaint> to ensure
137 that the data coming in is suitable for the table. If you're using the
138 default C<CDBI> model, then, you're going to need to set up your tables
139 in a way that makes C<FromCGI> happy.
140
141 The data is untainted, and any errors are collected into a hash which is
142 passed to the template. We also pass back in the parameters, so that the
143 template can re-fill the form fields with the original values. The user
144 is then sent back to the C<edit> template.
145
146         if (my %errors = $obj->cgi_update_errors) {
147             # Set it up as it was:
148             $r->template_args->{cgi_params} = $r->params;
149             $r->template_args->{errors} = \%errors;
150             $r->template("edit");
151         }
152
153 Otherwise, the user is taken back to viewing the new object:
154
155     } else {
156         $r->template("view");
157     }
158     $r->objects([ $obj ]);
159
160 Notice that this does use hard-coded names for the templates to go to next.
161 Feel free to override this in your subclasses:
162
163     sub do_edit :Exported {
164         my ($class, $r) = @_;
165         $class->SUPER::do_edit($r);
166         $r->template("my_edit");
167     }
168
169 =head3 Digression on C<Class::DBI::FromCGI>
170
171 C<CGI::Untaint> is a mechanism for testing that incoming form data
172 conforms to various properties. For instance, given a C<CGI::Untaint>
173 object that encapsulates some C<POST> parameters, we can extract an
174 integer like so:
175
176     $h->extract(-as_integer => "score");
177
178 This checks that the C<score> parameter is an integer, and returns it if
179 it is; if not, C<< $h->error >> will be set to an appropriate error
180 message. Other tests by which you can extract your data are C<as_hex>
181 and C<as_printable>, which tests for a valid hex number and an ordinary
182 printable string respectively; there are other handlers available on
183 CPAN, and you can make your own, as documented in L<CGI::Untaint>.
184
185 To tell the C<FromCGI> handler what handler to use for each of your
186 columns, you need to use the C<untaint_columns> methods in the classes
187 representing your tables. For instance:
188
189     BeerDB::Beer->untaint_columns(
190         integer => ["score", ... ],
191     );
192
193 This must be done after the call to C<setup> in your handler, because
194 otherwise the model classes won't have been set up to inherit from
195 C<Class::DBI::FromCGI>.
196
197 Remember that if you want to use drop-downs to set the value of related
198 fields, such as the brewery for a beer, you need to untaint these as
199 something acceptable for the primary key of that table:
200
201     BeerDB::Beer->untaint_columns(
202         integer => ["score", "brewery", "style" ],
203         ...
204     );
205
206 This is usually integer, if you're using numeric IDs for your primary
207 key. If not, you probably want C<printable>, but you probably know what
208 you're doing anyway.
209
210 =head3 delete
211
212 The delete method takes a number of arguments and deletes those rows from the
213 database; it then loads up all rows and heads to the F<list> template.
214 You almost certainly want to override this to provide some kind of
215 authentication.
216
217 =head3 list
218
219 Listing, like viewing, is a matter of selecting objects for
220 presentation. This time, instead of a single object specified in the
221 URL, we want, by default, all the records in the table:
222
223     sub list :Exported {
224         my ($class, $r) = @_;
225         $r->objects([ $self->retrieve_all ])
226     }
227
228 However, things are slightly complicated by paging and ordering by
229 column; the default implementation also provides a C<Class::DBI::Pager>
230 object to the templates and uses that to retrieve the appropriate bit of
231 the data, as specified by the C<page> URL query parameter. See the
232 L<"pager"> template below.
233
234 =head3 search
235
236 Searching also uses paging, and creates a query from the C<POST>
237 parameters. It uses the F<list> template to display the objects once
238 they've been selected from the database.
239
240 =head2 The templates and macros
241
242 Once these actions have done their work, they hand a set of objects to
243 the templates; if you haven't specified your own custom template
244 globally or for a given class, you'll be using the factory specified
245 template. Let's take a look now at each of these and how they're put
246 together.
247
248 The beauty of the factory specified templates is that they make use of
249 the classes' metadata as supplied by the view class. Although you're
250 strongly encouraged to write your own templates, in which you don't need
251 to necessarily be as generic, the factory templates will always do the
252 right thing for any class without further modification, and as such are
253 useful examples of how to build Maypole templates.
254
255 =head3 Commonalities
256
257 There are certain common elements to a template, and these are extracted
258 out. For instance, all the templates call the F<header> template to
259 output a HTML header, and nearly all include the F<macros> template to
260 load up some common template functions. We'll look at these common
261 macros as we come across them.
262
263 =head3 F<view> 
264
265 template view
266
267 =head3 F<edit>
268
269 The F<edit> template is pretty much the same as F<view>, but it uses 
270 L<Class::DBI::AsForm>'s
271 C<to_field> method on each column of an object to return a C<HTML::Element>
272 object representing a form element to edit that property. These elements
273 are then rendered to HTML with C<as_HTML> or to XHTML with C<as_XML>.
274 It expects to see a list of
275 editing errors, if any, in the C<errors> template variable:
276
277      FOR col = classmetadata.columns;
278         NEXT IF col == "id";
279         "<P>";
280         "<B>"; classmetadata.colnames.$col; "</B>";
281         ": ";
282             item.to_field(col).as_HTML;
283         "</P>";
284         IF errors.$col;
285             "<FONT COLOR=\"#ff0000\">"; errors.$col; "</FONT>";
286         END;
287     END;
288
289 =head3 F<list>
290
291 Browsing records and search results are both handled by the F<list> template.
292 The C<search> template argument is used to distinguish between the two cases:
293
294     [% IF search %]
295     <h2> Search results </h2>
296     [% ELSE %]
297     <h2> Listing of all [% classmetadata.plural %]</h2>
298     [% END %]
299
300 =head3 F<pager>
301
302 The pager template controls the list of pages at the bottom (by default)
303 of the list and search views. It expects a C<pager> template argument
304 which responds to the L<Data::Page> interface.
305 There's a description of how it works in
306 L<the Template Toolkit section|Maypole::Manual::View/"The Template Toolkit">
307 of the View chapter.
308
309 =head3 F<macros>
310
311 The F<macros> template is included at the start of most other templates
312 and makes some generally-useful template macros available:
313
314 =over
315
316 =item C<link(table, command, additional, label)>
317
318 This makes an HTML link pointing to C</base/table/command/additional>
319 labelled by the text in I<label>. C<base> is the template variable that
320 contains the base URL of this application.
321
322 =item C<maybe_link_view(object)>
323
324 C<maybe_link_view> takes something returned from the database - either
325 some ordinary data, or an object in a related class expanded by a
326 has-a relationship. If it is an object, it constructs a link to the view
327 command for that object. Otherwise, it just displays the data.
328
329 =item C<display_line(object)>
330
331 C<display_line> is used in the list template to display a row from the
332 database, by iterating over the columns and displaying the data for each
333 column. It misses out the C<id> column by default, and magically
334 URLifies columns called C<url>. This may be considered too much magic
335 for some.
336
337 =item C<button(object, action)>
338
339 This is a simple button that is submitted to C</base/table/action/id>,
340 where C<table> and C<id> are those belonging to the database row C<object>.
341 The button is labelled with the name of the action.
342 You can see buttons on many pages, including lists.
343
344 =item C<view_related(object)>
345
346 This takes an object, and looks up its C<related_accessors>; this gives
347 a list of accessor methods that can be called to get a list of related
348 objects. It then displays a title for that accessor, (e.g. "Beers" for a
349 C<brewery.beers>) calls the accessor, and displays a list of the results.
350 You can see it in use at the bottom of the standard view pages.
351
352 =back
353
354 =begin TODO
355
356 =head2 Customizing Generic CRUD Applications
357
358 =end TODO
359
360 =head2 Links
361
362 L<Contents|Maypole::Manual>,
363 Next L<The Request Workflow|Maypole::Manual::Workflow>,
364 Previous L<Maypole View Classes|Maypole::Manual::View>,
365