To start refactoring my application, I started by refactoring BeerDB and wrote it up. The updated pod is on the wiki. The new section is below. I would appreciate comments or suggestions.

A couple of questions though.

I note from the documentation in Maypole::Model::CDBI::Plain that (for the BeerDB) we're asked to create our model classes in BeerDB::Beer, BeerDB::Style etc. What If I don't want to do that? How do I configure CDBI::Plain/Maypole to look for say the classes qw/ Beer Beer::Brewery Beer::Style/ etc?

My brief experiment showed me that the untaint statements don't work if they're moved into the model classes, so for example the statement

BeerDB::Brewery->untaint_columns( printable => [qw/name notes url/]);

in Brewery.pm doesn't work (the error message is something like:

BeerDB::Beer can't load BeerDB::Brewery: Can't locate object method "untaint_columns" via package "BeerDB::Brewery" at /usr/local/src/ beer/lib//BeerDB/Brewery.pm line 6.\nCompilation failed in require at /Library/Perl/5.8.6/Class/DBI.pm line 1208. at /Library/Perl/5.8.6/ Class/DBI/Relationship/HasA.pm line 22\nCompilation failed in require at /usr/local/src/beer/lib//BeerDB.pm line 3.\nBEGIN failed-- compilation aborted at /usr/local/src/beer/lib//BeerDB.pm line 3. \nCompilation failed in require at (eval 19) line 3.\n

I've kept it in BeerDB.pm for now, but it seems to me that this stuff would be better with the model than the driver. Is there an easy way to fix this, or have I misunderstood?

Cheers

kd


^-^-^-^ Updated docs

=head1 Structuring your code.

At this point, you should have a working Beer database. In about 20 lines of code.

The standard BeerDB contains four tables: beer, brewery, pub and style. Each of these tables has an associated class which are BeerDB::Beer, BeerDB::Brewery, BeerDB::Pub, BeerDB::Style. Although this is a simple database, and Maypole works well, out of the box with the BeerDB, it's worth separating out each class into separate files. Initially, this process is a bit of a fiddle, but it results in much more maintainable code later. Here's how to do it with the standard beeerdb.

BeerDB.pm lives in /usr/local/src/beer/lib, we can create a directory called BeerDB, and then create the following files:

=over

=item DBI.pm

=item Beer.pm

=item Brewery.pm

=item Handpump.pm

=item Pub.pm

=item Style.pm

=back

=head2 The database driver code code

=over

=item DBI.pm

package BeerDB::DBI;
use base 'Class::DBI';
BeerDB::DBI->connection('dbi:mysql:beer', 'root', '');
1;

=item Beer.pm

package BeerDB::Beer;
use base 'BeerDB::DBI';
BeerDB::Beer->table('beer');
BeerDB::Beer->columns(All => qw/brewery style name url score price/);
BeerDB::Beer->has_a(brewery => 'BeerDB::Brewery');
BeerDB::Beer->has_a(style => 'BeerDB::Style');
BeerDB::Beer->has_many(beers => [BeerDB::Handpump => 'beer']);
BeerDB::Beer->has_many(pubs => [BeerDB::Handpump => 'pub']);
1;

=item Brewery.pm

package BeerDB::Brewery;
use base 'BeerDB::DBI';
BeerDB::Brewery->table('brewery');
BeerDB::Brewery->columns(All => qw/name url notes/);
BeerDB::Brewery->has_many(beers => "BeerDB::Beer");
1;

=item Handpump.pm

package BeerDB::Handpump;
use base 'BeerDB::DBI';
BeerDB::Handpump->table('handpump');
BeerDB::Handpump->columns(All => qw/beer pub/);
BeerDB::Handpump->has_a(beer => 'BeerDB::Beer');
BeerDB::Handpump->has_a(pub => 'BeerDB::Pub');
1;

=item Pub.pm

package BeerDB::Pub;
use base 'BeerDB::DBI';
BeerDB::Pub->table('pub');
BeerDB::Pub->columns(All => qw/name url notes/);
1;

=item Style.pm

package BeerDB::Style;
use base 'BeerDB::DBI';
BeerDB::Style->table('style');
BeerDB::Style->columns(All => qw/name notes/);
BeerDB::Style->has_many(beers => 'BeerDB::Beer');
1;

=back

So that's quite a lot of code (for a trivial Maypole application). Now we need to wrap it all up in a driver class fro Maypole: this lives (according to my scheme) in /usr/local/src/beer/lib

=over

=item BeerDB.pm

package BeerDB;
use base 'Maypole::Application';
use BeerDB::Beer;
use BeerDB::Brewery;
use BeerDB::Handpump;
use BeerDB::Pub;
use BeerDB::Style;

BeerDB->config->model('Maypole::Model::CDBI::Plain');
BeerDB->setup([qw/BeerDB::Beer BeerDB::Brewery BeerDB::Handpump BeerDB::Pub Beer

DB::Style/]);

BeerDB->config->uri_base("http://localhost/beer";);
BeerDB->config->template_root("/usr/local/src/beer/templates/");
BeerDB->config->rows_per_page(10);
BeerDB->config->display_tables([qw[beer brewery pub style]]);
BeerDB::Beer->untaint_columns(
                             printable => [qw/abv name price notes/],
                             integer => [qw/style brewery score/],
                             date => [ qw/date/],
                            );
BeerDB::Brewery->untaint_columns( printable => [qw/name notes url/]);
BeerDB::Style->untaint_columns( printable => [qw/name notes/] );
1;

=back

-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Maypole-users mailing list
Maypole-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/maypole-users

Reply via email to