1 =head1 Maypole Model Classes
5 =head2 Maypole::Model::CDBI
7 Maypole model classes are pretty evil. The very first thing a Maypole
8 model class will do in a Maypole application is to cause a load of
9 table-based classes to come into being, and then assimilate them.
11 What I mean by this is that when you set up a Maypole application, in
12 your driver class, you'll say something like this:
14 BeerDB->setup("dbi:mysql:beerdb");
16 C<setup> is a Maypole method, and it hands its parameter to the model
17 class. In our case, the model class is a DBI connect string, because
18 that's what C<Maypole::Model::CDBI>, the C<Class::DBI>-based model
19 expects. C<Maypole::Model::CDBI> has a method called C<setup_database>
20 that creates all the C<Class::DBI> table classes after connecting to the
21 database with that connect string. It does this by using
22 C<Class::DBI::Loader>, a utility module which asks a database
23 about its schema and sets up classes such as C<BeerDB::Beer> to inherit
24 from C<Class::DBI>. This is just doing automatically what we did
25 manually in our examples above.
27 Now it gets interesting. The names of these classes are stashed away in
28 the application's configuration, and then Maypole forcibly has these
29 classes inherit from the model class. Our C<BeerDB::Beer> now inherits
30 both from C<Class::DBI> and C<Maypole::Model::CDBI>.
32 This is useful for two reasons. The first reason is that
33 C<Maypole::Model::CDBI> is stuffed full of C<Class::DBI> goodies that
34 make writing Maypole applications a lot easier:
36 package Maypole::Model::CDBI;
37 use base qw(Maypole::Model::Base Class::DBI);
38 use Class::DBI::AsForm;
39 use Class::DBI::FromCGI;
40 use Class::DBI::Loader;
41 use Class::DBI::AbstractSearch;
42 use Class::DBI::Plugin::RetrieveAll;
43 use Class::DBI::Pager;
45 We'll meet most of these goodies in L<StandardTemplates.pod>, where we
46 explain how C<Maypole::Model::CDBI> works.
48 The second reason why we want our table classes to inherit from
49 C<Maypole::Model::CDBI> is because C<CDBI> provides a useful set of
50 default actions. So what's an action, and why are they useful?
52 =head2 Extending a model class with actions
54 Maypole operates primarily by turning URLs into method calls on a model
55 class. All that the model stage of Maypole's operation does, when it
56 comes down to it, is maintain a mapping of tables to classes, and
57 despatch a HTTP request to a method call on the relevant table class. This
58 means that if you request a URL such as
60 http://localhost/beerdb/brewery/delete/20
62 Maypole's first stage of operation is to turn that into
63 C<BeerDB::Brewery-E<gt>delete(20)>. Now, it's slightly more complex than
64 that. Firstly because it doesn't actually pass the parameter C<20>, but
65 it passes an object representing row 20 in the database, but we can
66 gloss over that for the second. No, the real issue is that Maypole does
67 not allow you to call any method in the table class; that would be
70 Instead, Maypole makes a distinction between the kind of methods that
71 only the class itself and other Perl code can call, and the kind of
72 methods that anyone can call from a URL. This latter set of methods are
73 called B<exported> methods, and exporting is done with by means of Perl
74 attributes. You define a method to be exported like so:
78 This will allow the user to access C</beerdb/beer/drink> over the web.
79 An exported method accompanied with a template to render its output is
80 sometimes called an B<action>.
82 Maypole model classes like C<Maypole::Model::CDBI> come with a
83 relatively handy set of actions which are all you need to set up a CRUD
84 database front-end: viewing a row in a database, editing it, adding a
85 new one, deleting, and so on. The most important thing about Maypole,
86 though, is that it doesn't stop there. You can add your own.
88 For instance, in our beer database application, we could create a
89 C<BeerDB::Beer> package, and put some additional actions in there.
92 sub top_five :Exported {
94 $r->{objects} = [ ($r->retrieve_all_sorted_by("score"))[-5..-1] ];
97 Our action is called as a class method with the Maypole request object.
98 It uses the C<Class::DBI::Plugin::RetrieveAll> module's
99 C<retrieve_all_sorted_by> mixin to get the top five scoring beers, and
100 puts these in the C<objects> slot of the request of object. Next, the
101 view class will come along and process the C<top_five> template with
104 We'll look more at how to put together actions in the
105 L<StandardTemplates.pod> chapter and our case studies.
107 =head2 What Maypole wants from a model
109 =head2 Building your own model class