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
20 templates 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
27 templates that cover every possible situation.
28
29 The standard actions
30 Remember that actions are just subroutines in the model classes with an
31 Exported attribute. A simple, uncustomized Maypole model class, such
32 as one of the classes in the beer database application, provides the
33 following default actions - that is, provides access to the following
34 URLs:
35
36 "/[table]/view/[id]"
37 This takes the ID of an object in a table, retrieves the object, and
38 presents it to the view template.
39
40 "/[table]/edit/[id]"
41 This is the same as "view", but uses the edit template to provide a
42 web form to edit the object; it submits to "do_edit".
43
44 "/[table]/do_edit/[id]"
45 When called with an ID, the "do_edit" action provides row editing.
46
47 "/[table]/do_edit/"
48 When called without an ID, the "do_edit" action provides row
49 creation.
50
51 "/[table]/delete/id"
52 This deletes a row, returning to the "list" page.
53
54 "/[table]/list/"
55 This provides a paged list of the table suitable for browsing.
56
57 "/[table]/do_search/"
58 This handles a search query and presents the search results back to
59 the list template. Previously this was called search, but obviously
60 that clashes with a lot of stuff, and that usage is now deprecated.
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
83 separated 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"
130 methods of Class::DBI::FromCGI to turn "POST" parameters into database
131 table data. This in turn uses CGI::Untaint to ensure that the data
132 coming in is suitable for the table. If you're using the default "CDBI"
133 model, then, you're going to need to set up your tables in a way that
134 makes "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
167 conforms 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
181 columns, you need to use the "untaint_columns" methods in the classes
182 representing 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 do_delete
206
207 The do_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
209 template. You almost certainly want to override this to provide some
210 kind of authentication.
211
212 Previously this was called delete, but obviously that clashes with a
213 lot of stuff, and that usage is now deprecated.
214
215 list
216
217 Listing, like viewing, is a matter of selecting objects for
218 presentation. This time, instead of a single object specified in the
219 URL, we want, by default, all the records in the table:
220
221 sub list :Exported {
222 my ($class, $r) = @_;
223 $r->objects([ $self->retrieve_all ])
224 }
225
226 However, things are slightly complicated by paging and ordering by
227 column; the default implementation also provides a "Class::DBI::Pager"
228 object to the templates and uses that to retrieve the appropriate bit
229 of the data, as specified by the "page" URL query parameter. See the
230 "pager" template below.
231
232 search
233
234 Searching also uses paging, and creates a query from the "POST"
235 parameters. It uses the list template to display the objects once
236 they've been selected from the database.
237
238 The templates and macros
239 Once these actions have done their work, they hand a set of objects to
240 the templates; if you haven't specified your own custom template
241 globally or for a given class, you'll be using the factory specified
242 template. Let's take a look now at each of these and how they're put
243 together.
244
245 The beauty of the factory specified templates is that they make use of
246 the classes' metadata as supplied by the view class. Although you're
247 strongly encouraged to write your own templates, in which you don't
248 need to necessarily be as generic, the factory templates will always do
249 the right thing for any class without further modification, and as such
250 are useful examples of how to build Maypole templates.
251
252 Commonalities
253
254 There are certain common elements to a template, and these are
255 extracted out. For instance, all the templates call the header template
256 to output a HTML header, and nearly all include the macros template to
257 load up some common template functions. We'll look at these common
258 macros as we come across them.
259
260 view
261
262 template view
263
264 edit
265
266 The edit template is pretty much the same as view, but it uses
267 Maypole::Model::CDBI::AsForm's "to_field" method on each column of an
268 object to return a "HTML::Element" object representing a form element
269 to edit that property. These elements are then rendered to HTML with
270 "as_HTML" or to XHTML with "as_XML". It expects to see a list of
271 editing errors, if any, in the "errors" template variable:
272
273 FOR col = classmetadata.columns;
274 NEXT IF col == "id";
275 "<P>";
276 "<B>"; classmetadata.colnames.$col; "</B>";
277 ": ";
278 item.to_field(col).as_HTML;
279 "</P>";
280 IF errors.$col;
281 "<FONT COLOR=\"#ff0000\">"; errors.$col; "</FONT>";
282 END;
283 END;
284
285 list
286
287 Browsing records and search results are both handled by the list
288 template. The "search" template argument is used to distinguish
289 between the two cases:
290
291 [% IF search %]
292 <h2> Search results </h2>
293 [% ELSE %]
294 <h2> Listing of all [% classmetadata.plural %]</h2>
295 [% END %]
296
297 pager
298
299 The pager template controls the list of pages at the bottom (by
300 default) of the list and search views. It expects a "pager" template
301 argument which responds to the Data::Page interface. There's a
302 description of how it works in the Template Toolkit section of the View
303 chapter.
304
305 macros
306
307 The macros template is included at the start of most other templates
308 and makes some generally-useful template macros available:
309
310 "link(table, command, additional, label)"
311 This makes an HTML link pointing to
312 "/base/table/command/additional" labelled by the text in label.
313 "base" is the template variable that contains the base URL of this
314 application.
315
316 maybe_link_view(object)
317 "maybe_link_view" takes something returned from the database -
318 either some ordinary data, or an object in a related class expanded
319 by a has-a relationship. If it is an object, it constructs a link
320 to the view command for that object. Otherwise, it just displays
321 the data.
322
323 display_line(object)
324 "display_line" is used in the list template to display a row from
325 the database, by iterating over the columns and displaying the data
326 for each column. It misses out the "id" column by default, and
327 magically URLifies columns called "url". This may be considered too
328 much magic for some.
329
330 "button(object, action)"
331 This is a simple button that is submitted to
332 "/base/table/action/id", where "table" and "id" are those belonging
333 to the database row "object". The button is labelled with the name
334 of the action. You can see buttons on many pages, including lists.
335
336 view_related(object)
337 This takes an object, and looks up its "related_accessors"; this
338 gives a list of accessor methods that can be called to get a list
339 of related objects. It then displays a title for that accessor,
340 (e.g. "Beers" for a "brewery.beers") calls the accessor, and
341 displays a list of the results. You can see it in use at the
342 bottom of the standard view pages.
343
344 Links
345 Contents, Next The Request Workflow, Previous Maypole View Classes,
346
347
348
349perl v5.36.0 2023-01-M2a0ypole::Manual::StandardTemplates(3)