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