X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=doc%2FModel.pod;h=bc54ffdb8105ef81a9e57e260c820816fbb445f1;hb=85968ef28d078868c8e2865a3e76f81ddd4ec94c;hp=c5f5b18ec9a3db77fd09d8742899433967887750;hpb=81302aff5cf7e25674ca3af7ba79c5b3fa5f4e20;p=maypole.git diff --git a/doc/Model.pod b/doc/Model.pod index c5f5b18..bc54ffd 100644 --- a/doc/Model.pod +++ b/doc/Model.pod @@ -4,8 +4,106 @@ =head2 Maypole::Model::CDBI +Maypole model classes are pretty evil. The very first thing a Maypole +model class will do in a Maypole application is to cause a load of +table-based classes to come into being, and then assimilate them. + +What I mean by this is that when you set up a Maypole application, in +your driver class, you'll say something like this: + + BeerDB->setup("dbi:mysql:beerdb"); + +C is a Maypole method, and it hands its parameter to the model +class. In our case, the model class is a DBI connect string, because +that's what C, the C-based model +expects. C has a method called C +that creates all the C table classes after connecting to the +database with that connect string. It does this by using +C, a utility module which asks a database +about its schema and sets up classes such as C to inherit +from C. This is just doing automatically what we did +manually in our examples above. + +Now it gets interesting. The names of these classes are stashed away in +the application's configuration, and then Maypole forcibly has these +classes inherit from the model class. Our C now inherits +both from C and C. + +This is useful for two reasons. The first reason is that +C is stuffed full of C goodies that +make writing Maypole applications a lot easier: + + package Maypole::Model::CDBI; + use base qw(Maypole::Model::Base Class::DBI); + use Class::DBI::AsForm; + use Class::DBI::FromCGI; + use Class::DBI::Loader; + use Class::DBI::AbstractSearch; + use Class::DBI::Plugin::RetrieveAll; + use Class::DBI::Pager; + +We'll meet most of these goodies in L, where we +explain how C works. + +The second reason why we want our table classes to inherit from +C is because C provides a useful set of +default actions. So what's an action, and why are they useful? + =head2 Extending a model class with actions +Maypole operates primarily by turning URLs into method calls on a model +class. All that the model stage of Maypole's operation does, when it +comes down to it, is maintain a mapping of tables to classes, and +despatch a HTTP request to a method call on the relevant table class. This +means that if you request a URL such as + + http://localhost/beerdb/brewery/delete/20 + +Maypole's first stage of operation is to turn that into +Cdelete(20)>. Now, it's slightly more complex than +that. Firstly because it doesn't actually pass the parameter C<20>, but +it passes an object representing row 20 in the database, but we can +gloss over that for the second. No, the real issue is that Maypole does +not allow you to call any method in the table class; that would be +somewhat insecure. + +Instead, Maypole makes a distinction between the kind of methods that +only the class itself and other Perl code can call, and the kind of +methods that anyone can call from a URL. This latter set of methods are +called B methods, and exporting is done with by means of Perl +attributes. You define a method to be exported like so: + + sub drink :Exported { + +This will allow the user to access C over the web. +An exported method accompanied with a template to render its output is +sometimes called an B. + +Maypole model classes like C come with a +relatively handy set of actions which are all you need to set up a CRUD +database front-end: viewing a row in a database, editing it, adding a +new one, deleting, and so on. The most important thing about Maypole, +though, is that it doesn't stop there. You can add your own. + +For instance, in our beer database application, we could create a +C package, and put some additional actions in there. + + package BeerDB::Beer; + sub top_five :Exported { + my ($class, $r) = @_; + $r->{objects} = [ ($r->retrieve_all_sorted_by("score"))[-5..-1] ]; + } + +Our action is called as a class method with the Maypole request object. +It uses the C module's +C mixin to get the top five scoring beers, and +puts these in the C slot of the request of object. Next, the +view class will come along and process the C template with +these five beers. + +We'll look more at how to put together actions in the +L chapter and our case studies. + =head2 What Maypole wants from a model =head2 Building your own model class