1Maypole::Manual::StandaUrsdeTremCpolnattreisb(u3t)ed PerMlayDpoocluem:e:nMtaantuiaoln::StandardTemplates(3)
2
3
4

NAME

6       Maypole::Manual::StandardTemplates - Maypole's Standard Templates and
7       Actions
8

DESCRIPTION

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)
Impressum