]> git.decadent.org.uk Git - maypole.git/blobdiff - lib/Maypole/Manual/Inheritance.pod
Modified setup_model() to load any available custom table classes.
[maypole.git] / lib / Maypole / Manual / Inheritance.pod
index 2dd0eaf0f6e2048d2e6b4569eeebf9115c5afd68..6c6c6b77eba53e34624cf88766ec64bb52017412 100644 (file)
@@ -16,8 +16,7 @@ application.
 \r
         +\r
         |\r
-    +--  --+\r
-        |\r
+     +-   -+\r
        |\r
        +\r
        \r
@@ -37,35 +36,36 @@ A minimal Maypole application (such as the Beer database) consists of a
 custom driver class (BeerDB.pm), a set of auto-generated model classes, and a \r
 view class: \r
 \r
-                  THE DRIVER\r
+\r
+           THE DRIVER\r
                                           +------- init() is a factory method,\r
                    1      Maypole         |           it sets up the view\r
    Maypole::Config <----- config();       |              classes\r
    model();               init(); *-------+                           THE VIEW\r
-    |                     view_object(); -------+              \r
+    |                     view_object(); -------+\r
     |    +--------------* setup();              |      Maypole::View::Base\r
     |    |                   +                  |              +\r
     |    |                   |                  |     1        |\r
-    |    |               Apache::MVC *-----+    +-----> Maypole::View::TT\r
-    |    |                   +             |             (or another view class)\r
-    |    |                   |             |\r
-    |    |                PLUGINS          |\r
-    |    |                   +             |\r
-    |    |                   |             +----- or CGI::Maypole\r
-    |    |                BeerDB                   or MasonX:::Maypole\r
+    |    |    PLUGINS    Apache::MVC *-----+    +-----> Maypole::View::TT\r
+    |    |       +           +             |             (or another view class)\r
+    |    |       |           |             |\r
+    |    |       +-----+-----+             |\r
+    |    |             |                   |\r
+    |    |           BeerDB                +----- or CGI::Maypole\r
+    |    |                                         or MasonX:::Maypole\r
     |    |\r
     |   setup() is a factory method,\r
     |     it sets up the model\r
     |         classes\r
     |\r
-    |                                 THE MODEL\r
+    |                                             THE MODEL\r
     |\r
-    |  Maypole::Model::Base   Class::DBI\r
-    |             +             +\r
-    |             |             |                             \r
-    +-------> Maypole::Model::CDBI                            \r
-                      +                                       \r
-                      |                                       \r
+    |  Maypole::Model::Base    Class::DBI\r
+    |             +             +      +\r
+    |             |             |      |\r
+    +-------> Maypole::Model::CDBI   Class::DBI::<db_driver>\r
+                      +                     +\r
+                      |                     |\r
            +------------+--------+-------+---------+\r
            |            |        |       |         |\r
        BeerDB::Pub      |   BeerDB::Beer | BeerDB::Brewery\r
@@ -76,24 +76,20 @@ view class:
           pub();                      BeerDB::Style\r
           beer();                     beers();\r
 \r
-\r
 =head2 What about Maypole::Application - loading plugins\r
 \r
-The main job of L<Maypole::Application> is to insert the plugins into the \r
-hierarchy. It ensures that L<BeerDB> inherits from the first plugin, which \r
-inherits from the next, etc., until the last plugin inherits from the frontend. \r
-\r
-It is also the responsibility of L<Maypole::Application> to decide which \r
-frontend to use. \r
+The main job of L<Maypole::Application> is to insert the plugins into the\r
+hierarchy. It is also the responsibility of L<Maypole::Application> to decide\r
+which frontend to use. It builds the list of plugins, then pushes them onto the\r
+driver's C<@ISA>, then pushes the frontend onto the end of the driver's C<@ISA>.\r
+So method lookup first searches all the plugins, before searching the frontend\r
+and finally L<Maypole> itself.\r
 \r
 From Maypole 2.11, L<Maypole::Application> makes no appearance in the\r
 inheritance structure of a Maypole application. (In prior versions,\r
 L<Maypole::Application> would make itself inherit the plugins, and then insert\r
 itself in the hierarchy, but this was unnecessary).\r
 \r
-The order of inheritance is the same as the order in which plugins are supplied \r
-in the C<use Maypole::Application> statement. \r
-\r
 =head2 Who builds the model?\r
 \r
 First, remember we are talking about the standard, unmodified Maypole here. \r
@@ -102,10 +98,13 @@ customised model.
 \r
 The standard model is built in 3 stages. \r
 \r
-First, C<Maypole::setup> calls C<setup_database> on the Maypole model class, in\r
-this case L<Maypole::Model::CDBI>. C<setup_database> then uses\r
+First, C<Maypole::setup_model> calls C<setup_database> on the Maypole model\r
+class, in this case L<Maypole::Model::CDBI>. C<setup_database> then uses\r
 L<Class::DBI::Loader> to autogenerate individual L<Class::DBI> classes for each\r
 of the tables in the database (C<BeerDB::Beer>, C<BeerDB::Pub> etc).\r
+L<Class::DBI::Loader> identifies the appropriate L<Class::DBI> subclass and\r
+inserts it into each of these table classes' C<@ISA> ( C<<\r
+Class::DBI::<db_driver> >> in the diagrams)..\r
 \r
 Next, C<Maypole::setup> B<unshifts> L<Maypole::Model::CDBI> onto the C<@ISA> \r
 array of each of these classes. \r
@@ -181,8 +180,8 @@ C<BeerDB2::Beer>, you would write:
     use base 'OfflineBeer::Beer';\r
     1;\r
     \r
-This package will be loaded automatically during C<setup()>, and\r
-C<BeerDB2::Maypole::Model> is B<unshifted> onto it's C<@ISA>. \r
+From Maypole 2.11, this package will be loaded automatically during C<setup()>,\r
+and C<BeerDB2::Maypole::Model> is B<unshifted> onto it's C<@ISA>.\r
 \r
 Configure relationships either in the individual C<OfflineBeer::*> classes, or\r
 else all together in C<OfflineBeer> itself i.e. not in the Maypole model. This \r
@@ -195,15 +194,16 @@ The resulting model looks like this:
                                           |\r
    Maypole::Model::Base                   |\r
            +                              |\r
-           |       +----------------------+-----------------+\r
-           |       |                                        |\r
-           |       |                                        |\r
-     Maypole::Model::CDBI                                   |     OFFLINE\r
-             +                                              |        MODEL\r
-             |                                              |\r
-     BeerDB2::Maypole::Model                           OfflineBeer\r
-       +                                                    +\r
-       |                                                    |\r
+           |       +-----------------+----+-----------------+\r
+           |       |                 |                      |\r
+           |       |                 |                      |\r
+     Maypole::Model::CDBI            |                      |     OFFLINE\r
+             +                       |                      |        MODEL\r
+             |                       |                      |\r
+     BeerDB2::Maypole::Model  Class::DBI::<db_driver>  OfflineBeer\r
+       +                             +                      +\r
+       |                             |                      |\r
+       +-----------------------------+                      |\r
        |                                                    |\r
        +--- BeerDB2::Pub --------+ OfflineBeer::Pub --------+\r
        |                           beers();                 |\r
@@ -227,10 +227,10 @@ The resulting model looks like this:
 \r
 =head3 Features\r
 \r
-Non-Maypole applications using the Offline model are completely isolated from\r
+1. Non-Maypole applications using the Offline model are completely isolated from\r
 the Maypole application, and need not know it exists at all.\r
 \r
-Methods defined in the Maypole table classes, override methods defined in the\r
+2. Methods defined in the Maypole table classes, override methods defined in the\r
 Offline table classes, because C<BeerDB2::Maypole::Model> was unshifted onto the\r
 beginning of each Maypole table class's C<@ISA>. Perl's depth first,\r
 left-to-right method lookup from e.g. C<BeerDB2::Beer> starts in\r
@@ -238,13 +238,22 @@ C<BeerDB2::Beer>, then C<BeerDB2::Maypole::Model>, C<Maypole::Model::CDBI>,
 C<Maypole::Model::Base>, and C<Class::DBI>, before moving on to\r
 C<OfflineBeer::Beer> and finally C<OfflineBeer>.\r
 \r
-Methods defined in the Maypole model base class (C<BeerDB2::Maypole::Model>),\r
+B<CAVEAT> - if your Offline model overrides L<Class::DBI> methods, these methods\r
+will B<not> be overridden when called from the Maypole application, because the\r
+Maypole model provides an alternative path to L<Class::DBI> which is searched\r
+first. The solution is to place such methods in a separate package, e.g.\r
+C<OfflineBeer::CDBI>. Place this B<first> in the C<@ISA> of both\r
+C<BeerDB2::Maypole::Model> and C<OfflineBeer>. Note that C<OfflineBeer::CDBI>\r
+does not itself need to inherit from L<Class::DBI>.\r
+\r
+3. Methods defined in the Maypole model base class (C<BeerDB2::Maypole::Model>),\r
 override methods in the individual Offline table classes, and in the Offline\r
 model base class (C<Offline>). \r
 \r
-Relationships defined in the Offline classes are inherited by the Maypole model.\r
+4. Relationships defined in the Offline classes are inherited by the Maypole\r
+model.\r
 \r
-The Maypole model has full access to the underlying Offline model. \r
+5. The Maypole model has full access to the underlying Offline model. \r
 \r
 =head3 Theory \r
 \r
@@ -262,3 +271,16 @@ Whatever label you prefer to use, this approach provides for clear separation of
 concerns between the underlying model and the web/user interface, and that's\r
 what it's all about.\r
           \r
+=head1 AUTHOR\r
+\r
+David Baird, C<< <cpan@riverside-cms.co.uk> >>\r
+\r
+=head1 COPYRIGHT & LICENSE\r
+\r
+Copyright 2005 David Baird, All Rights Reserved.\r
+\r
+This text is free documentation; you can redistribute it and/or modify it\r
+under the same terms as the Perl documentation itself.\r
+\r
+=cut\r
+\r