* Tests
* Better Documentation and more complex examples
-* Make templates XHTML compliant
package BeerDB;
use base 'Apache::MVC';
BeerDB->setup("dbi:mysql:beerdb");
- BeerDB->config->{uri_base} = "http://your.site/";
- BeerDB->config->{display_tables} = [qw[beer brewery pub style]];
+ BeerDB->config->uri_base("http://your.site/");
+ BeerDB->config->display_tables([qw[beer brewery pub style]]);
# Now set up your database:
# has-a relationships
# untaint columns
package BeerDB;
use base 'CGI::Maypole;
BeerDB->setup("dbi:mysql:beerdb");
- BeerDB->config->{uri_base} = "http://your.site/cgi-bin/beer.cgi/";
- BeerDB->config->{display_tables} = [qw[beer brewery pub style]];
+ BeerDB->config->uri_base("http://your.site/cgi-bin/beer.cgi/");
+ BeerDB->config->display_tables([qw[beer brewery pub style]]);
# Now set up your database:
# has-a relationships
# untaint columns
use UNIVERSAL::require;
use strict;
use warnings;
+use Maypole::Config;
our $VERSION = "1.8";
__PACKAGE__->mk_classdata($_) for qw( config init_done view_object );
__PACKAGE__->mk_accessors(
qw( ar params query objects model_class
args action template )
);
-__PACKAGE__->config( {} );
+__PACKAGE__->config( Maypole::Config->new() );
__PACKAGE__->init_done(0);
use Maypole::Constants;
sub { Maypole::handler( $calling_class, @_ ) };
}
my $config = $calling_class->config;
- $config->{model} ||= "Maypole::Model::CDBI";
- $config->{model}->require;
- die "Couldn't load the model class $config->{model}: $@" if $@;
- $config->{model}->setup_database( $config, $calling_class, @_ );
- for my $subclass ( @{ $config->{classes} } ) {
+ $config->model || $config->model("Maypole::Model::CDBI");
+ $config->model->require;
+ die "Couldn't load the model class $config->model: $@" if $@;
+ $config->model->setup_database( $config, $calling_class, @_ );
+ for my $subclass ( @{ $config->classes } ) {
no strict 'refs';
- 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");
}
}
sub init {
my $class = shift;
my $config = $class->config;
- $config->{view} ||= "Maypole::View::TT";
- $config->{view}->require;
- die "Couldn't load the view class $config->{view}: $@" if $@;
- $config->{display_tables} ||= [ @{ $class->config->{tables} } ];
- $class->view_object( $class->config->{view}->new );
+ $config->view || $config->view("Maypole::View::TT");
+ $config->view->require;
+ die "Couldn't load the view class ".$config->view.": $@" if $@;
+ $config->display_tables || $config->display_tables([ $class->config->tables ]);
+ $class->view_object( $class->config->view->new );
$class->init_done(1);
}
sub handler_guts {
my $r = shift;
- $r->model_class( $r->config->{model}->class_of( $r, $r->{table} ) );
+ $r->model_class( $r->config->model->class_of( $r, $r->{table} ) );
my $applicable = $r->is_applicable;
unless ( $applicable == OK ) {
sub is_applicable {
my $self = shift;
my $config = $self->config;
- $config->{ok_tables} ||= $config->{display_tables};
- $config->{ok_tables} = { map { $_ => 1 } @{ $config->{ok_tables} } }
- if ref $config->{ok_tables} eq "ARRAY";
+ $config->ok_tables || $config->ok_tables($config->display_tables);
+ $config->ok_tables ({ map { $_ => 1 } @{ $config->ok_tables } })
+ if ref $config->ok_tables eq "ARRAY";
warn "We don't have that table ($self->{table})"
if $self->debug
- and not $config->{ok_tables}{ $self->{table} };
- return DECLINED() unless exists $config->{ok_tables}{ $self->{table} };
+ and not $config->ok_tables->{ $self->{table} };
+ return DECLINED() unless exists $config->ok_tables->{ $self->{table} };
# Does the action method exist?
my $cv = $self->model_class->can( $self->{action} );
package ProductDatabase;
use base 'Apache::MVC';
__PACKAGE__->set_database("dbi:mysql:products");
- ProductDatabase->config->{uri_base} = "http://your.site/catalogue/";
+ ProductDatabase->config->uri_base = "http://your.site/catalogue/";
ProductDatabase::Product->has_a("category" => ProductDatabase::Category);
# ...
Then your top-level application package should change the model class:
(Before calling C<setup>)
- ProductDatabase->config->{model} = "ProductDatabase::Model";
+ ProductDatabase->config->model("ProductDatabase::Model");
(The C<:Exported> attribute means that the method can be called via the
URL C</I<table>/supersearch/...>.)
sub parse_location {
my $self = shift;
- my $url = URI->new( shift @ARGV );
- my $root = URI->new( $self->config->{uri_base} )->path;
+ my $url = URI->new(shift @ARGV);
+ my $root = URI->new($self->config->uri_base)->path;
$self->{path} = $url->path;
$self->{path} =~ s/^$root//i if $root;
$self->parse_path;
--- /dev/null
+package Maypole::Config;
+use base qw(Class::Accessor);
+use attributes ();
+#use overload
+# '""' => sub { shift->stringify_self};
+use strict;
+use warnings;
+
+# Public accessors.
+__PACKAGE__->mk_accessors(
+ qw( view uri_base template_root model loader display_tables ok_tables
+ rows_per_page dsn user pass opts)
+ );
+
+# Should only be modified by model.
+ __PACKAGE__->mk_ro_accessors( qw(
+ classes
+ tables
+ table_to_class
+ ) );
+
+1;
+
+=head1 NAME
+
+Maypole::Config - Maypole Configuration Class
+
+=head1 DESCRIPTION
+
+This class stores all configuration data for your Maypole application.
+
+=head2 view
+
+The view class for your Maypole Application. Defaults to "Maypole::View::TT"
+
+=head2 display_tables
+
+=head2 ok_tables
+
+=head2 model
+
+=head2 loader
+
+=head2 uri_base
+
+=head2 classes
+
+=head2 rows_per_page
+
+=head2 dsn
+
+=head2 user
+
+=head2 pass
+
+=head2 opts
+
++head2 table_to_root
+
+=head2 template_root
sub do_pager {
my ( $self, $r ) = @_;
- if ( my $rows = $r->config->{rows_per_page} ) {
+ if ( my $rows = $r->config->rows_per_page ) {
return $r->{template_args}{pager} =
$self->pager( $rows, $r->query->{page} );
}
my %ok_columns = map { $_ => 1 } $self->columns;
if ( $order = $r->query->{order} and $ok_columns{$order} ) {
$order .= ( $r->query->{o2} eq "desc" && " DESC" );
+ }
+ $order;
}
- $order;
-}
sub list : Exported {
my ( $self, $r ) = @_;
}
sub setup_database {
- my ( $self, $config, $namespace, $dsn, $u, $p, $opts ) = @_;
- $dsn ||= $config->{dsn};
- $u ||= $config->{user};
- $p ||= $config->{pass};
- $opts ||= $config->{opts};
- $config->{dsn} = $dsn;
- $config->{loader} = Class::DBI::Loader->new(
+ my ($self, $config, $namespace, $dsn, $u, $p, $opts) = @_;
+ $dsn ||= $config->dsn;
+ $u ||= $config->user;
+ $p ||= $config->pass;
+ $opts ||= $config->opts;
+ $config->dsn($dsn);
+ $config->loader || $config->loader( Class::DBI::Loader->new(
namespace => $namespace,
- dsn => $dsn,
- user => $u,
- password => $p,
- options => $opts,
- );
+ dsn => $dsn,
+ user => $u,
+ password => $p,
+ options => $opts,
+ ) );
$config->{classes} = [ $config->{loader}->classes ];
$config->{tables} = [ $config->{loader}->tables ];
}
sub class_of {
my ( $self, $r, $table ) = @_;
- return $r->config->{loader}->_table2class($table);
+ return $r->config->loader->_table2class($table);
}
1;
sub paths {
my ( $self, $r ) = @_;
- my $root = $r->{config}{template_root} || $r->get_template_root;
+ my $root = $r->config->template_root || $r->get_template_root;
return (
$root,
(
sub vars {
my ( $self, $r ) = @_;
my $class = $r->model_class;
- my $base = $r->{config}->{uri_base};
+ my $base = $r->config->uri_base;
$base =~ s/\/+$//;
my %args = (
request => $r,
=head1 SYNOPSIS
- BeerDB->config->{view} = "Maypole::View::TT"; # The default anyway
+ BeerDB->config->view("Maypole::View::TT"); # The default anyway
=head1 DESCRIPTION
use Test::More;
use lib 'ex'; # Where BeerDB should live
BEGIN { if (eval { require BeerDB }) {
- plan tests => 5;
- } else { Test::More->import(skip_all =>"SQLite not working or BeerDB module not found: $@") }
+ plan tests => 3;
+ } else { Test::More->import(skip_all =>"SQLite not working or BeerDB module could not be loaded: $@") }
}
use Maypole::CLI qw(BeerDB);
use Maypole::Constants;
isa_ok( (bless {},"BeerDB") , "Maypole");
-@ARGV = ("http://localhost/beerdb/");
-is(BeerDB->handler, OK, "OK");
-like($Maypole::CLI::buffer, qr/frontpage/, "Got the front page");
-
-@ARGV = ("http://localhost/beerdb/beer/list");
-is(BeerDB->handler, OK, "OK");
-like($Maypole::CLI::buffer, qr/Organic Best/, "Found a beer in the list");
+like(BeerDB->call_url("http://localhost/beerdb/"), qr/frontpage/, "Got the front page");
+like(BeerDB->call_url("http://localhost/beerdb/beer/list"), qr/Organic Best/, "Found a beer in the list");
# Begin object list
[% FOR obj = objects %]
-- [% obj.name %]
+[%obj.id%]: [% obj.name %]
[% END %]
# End object list
--- /dev/null
+# Begin object list
+[% FOR obj = objects %]
+- [% obj.name %]
+[% END %]
+# End object list