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