Added a dummy table class to ex/BeerDB to support a couple of tests.
git-svn-id: http://svn.maypole.perl.org/Maypole/trunk@408
48953598-375a-da11-a14b-
00016c27c3ee
--- /dev/null
+package BeerDB::Base;
+use strict;
+use warnings;
+
+sub floob {}
+
+1;
--- /dev/null
+package BeerDB::Beer;
+use strict;
+use warnings;
+
+# do this to test we get the expected @ISA after setup_model()
+use base 'BeerDB::Base';
+
+sub fooey : Exported {}
+
+1;
A likely target for over-riding, if you need to build a customised model.
A likely target for over-riding, if you need to build a customised model.
+This method also ensures any code in custom model classes is loaded, so you
+don't need to load them in the driver.
+
- my $calling_class = shift;
- $calling_class = ref $calling_class if ref $calling_class;
+ $class = ref $class if ref $class;
- my $config = $calling_class->config;
+ my $config = $class->config;
$config->model || $config->model('Maypole::Model::CDBI');
$config->model->require or die sprintf
"Couldn't load the model class %s: %s", $config->model, $@;
$config->model || $config->model('Maypole::Model::CDBI');
$config->model->require or die sprintf
"Couldn't load the model class %s: %s", $config->model, $@;
- $config->model->setup_database($config, $calling_class, @_);
+ # among other things, this populates $config->classes
+ $config->model->setup_database($config, $class, @_);
foreach my $subclass ( @{ $config->classes } )
{
foreach my $subclass ( @{ $config->classes } )
{
unshift @{ $subclass . "::ISA" }, $config->model;
$config->model->adopt($subclass)
if $config->model->can("adopt");
unshift @{ $subclass . "::ISA" }, $config->model;
$config->model->adopt($subclass)
if $config->model->can("adopt");
-
- # TODO: I think we should also load these classes, in case there is any
- # custom code. It would save the developer from needing to put
- # lots of use MyApp::SomeTable statements in the driver, and should
- # help eliminate some of those annoying silent errors if there's a
- # syntax error.
+
+ # Load custom model code, if it exists - nb this must happen after the
+ # unshift, to allow code attributes to work
+ eval "use $subclass";
+ die "Error loading $subclass: $@"
+ if $@ and $@ !~ /Can\'t locate \S+ in \@INC/;
+------- init() is a factory method,\r
1 Maypole | it sets up the view\r
Maypole::Config <----- config(); | classes\r
+------- init() is a factory method,\r
1 Maypole | it sets up the view\r
Maypole::Config <----- config(); | classes\r
| it sets up the model\r
| classes\r
|\r
| it sets up the model\r
| classes\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
+------------+--------+-------+---------+\r
| | | | |\r
BeerDB::Pub | BeerDB::Beer | BeerDB::Brewery\r
\r
The standard model is built in 3 stages. \r
\r
\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> 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
\r
Next, C<Maypole::setup> B<unshifts> L<Maypole::Model::CDBI> onto the C<@ISA> \r
array of each of these classes. \r
use base 'OfflineBeer::Beer';\r
1;\r
\r
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
\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
|\r
Maypole::Model::Base |\r
+ |\r
|\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
| |\r
+--- BeerDB2::Pub --------+ OfflineBeer::Pub --------+\r
| beers(); |\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
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
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
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
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
-Methods defined in the Maypole model base class (C<BeerDB2::Maypole::Model>),\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
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
-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
-This class provides session related methods for Maypole such as unique id's for requests.
+This class provides session related methods for Maypole such as unique id's for
+requests.
-Currently it provides only the generate_unique_id() function, by checking the id's generated by this function and included in submitted forms, it is possible to see if a form has been submitted before.. implementing these checks is left to the developer of that application.
+Currently it provides only the generate_unique_id() function, by checking the
+id's generated by this function and included in submitted forms, it is possible
+to see if a form has been submitted before.. implementing these checks is left
+to the developer of that application.
-Further functionality is to be added here in later versions to provide easy access to sessions, either through plugins or builtin methods.
+Further functionality is to be added here in later versions to provide easy
+access to sessions, either through plugins or builtin methods.
my $uid = Maypole::Session::generate_unique_id()
my $uid = Maypole::Session::generate_unique_id()
-generates a unique id and returns it, requires no arguments but accepts size, default is 32.
+generates a unique id and returns it, requires no arguments but accepts size,
+default is 32.
-###################################################################################################
-###################################################################################################
+################################################################################
+################################################################################
-Currently implementing uniqueness tests of form submissions is left to the Maypole user, we plan to provide an optional default behaviour to automate this if required.
+Currently implementing uniqueness tests of form submissions is left to the
+Maypole user, we plan to provide an optional default behaviour to automate this
+if required.
use Test::More;
use lib 'ex'; # Where BeerDB should live
BEGIN {
use Test::More;
use lib 'ex'; # Where BeerDB should live
BEGIN {
"SQLite not working or BeerDB module could not be loaded: $@"
) if $@;
"SQLite not working or BeerDB module could not be loaded: $@"
) if $@;
}
use Maypole::CLI qw(BeerDB);
use Maypole::Constants;
}
use Maypole::CLI qw(BeerDB);
use Maypole::Constants;
'classdata.list_columns');
is ($classdata{related_accessors},'pubs','classdata.related_accessors');
'classdata.list_columns');
is ($classdata{related_accessors},'pubs','classdata.related_accessors');
+# test if successfully loaded customised model class
+can_ok(BeerDB::Beer => 'fooey'); # defined in BeerDB::Beer
+can_ok(BeerDB::Beer => 'floob'); # defined in BeerDB::Base
+is_deeply( [@BeerDB::Beer::ISA], [qw/Maypole::Model::CDBI Class::DBI::SQLite BeerDB::Base/] );