[Maypole] If you hated Maypole, you'll also dislike...
CUMMING, Joe, FM
Joe.CUMMING@rbos.com
Wed, 21 Jul 2004 13:29:16 +0100
Hi there,
I don't know if this is of any use, but I have been happily extending
Maypole "horizontally" for a while using a very minor change to the existing
framework.
I guess I don't understand it, but I think the "rubberband" approach might
be a bit complicated.
What I did was to add "views" to the config which did not correspond to
tables but which acted in the same way as existing model classes over
tables.
To have Maypole recognise & react to the views all you have to do is add the
views to the ok_tables config entry in Maypole.pm
$config->{ok_tables} = {map {$_ => 1} (@{$config->{display_tables}},
@{$config->{views}}) };
For example, in my website/database "Tennis" I have Players & Matches
corresponding to tables. I also have an "Admin" view which has no associated
table
Tennis->config->{display_tables} = [qw[players matches]];
Tennis->config->{views} = [qw[admin]];
You then just write Tennis::Admin package with the same structure as the
Tennis::Players or Tennis::Matches
------------------------------------------------------------------
package Tennis3::Admin;
use base 'Maypole::Model::CDBI';
use strict;
sub list :Exported(Protected) {
my ($self, $r) = @_;
$r->objects([ $self->search_current_matches() ]);
$r->{template} = "list";
}
__PACKAGE__->set_sql(current_matches => qq {select date > now() "current"
from matches});
------------------------------------------------------------------
The views need not correspond to any table, they can just execute
commands & then display a page as per usual.
The only drawback I found is that when I wanted to have a view execute
database commands I had to implement the db_Main method in the package to
return a db handle from one of $r->$config->{classes}.
Can anyone figure out how to have non "table tied" packages inherit properly
and have the db_Main of the setup database implemented.
Thanks,
Joe
p.s. the "protected" on the exported sub is something else I added so that
all methods which are so assigned need authentication. Saves having to do
custom "authenticate" methods
-----Original Message-----
From: maypole-admin@lists.netthink.co.uk
[mailto:maypole-admin@lists.netthink.co.uk] On Behalf Of Simon Cozens
Sent: 20 July 2004 23:24
To: Maypole List
Subject: [Maypole] If you hated Maypole, you'll also dislike...
I don't know quite how to describe my latest web application framework, or
how
to explain it. If I called it "an abstraction layer above Maypole", you
might
think that my code was soon going to disappear up its own backside. Maybe it
is.
While Maypole was designed to be extended "vertically", in the sense of
making
it very easy to add new actions to a class - one template, one method, and
you're done - it isn't so easy to extend "horizontally". You can't easily
add
new ideas and concepts (as represented by tables and classes) and have them
fit in nicely with the rest of the application.
This is a problem I looked at and solved when designing my Email::Store set
of
mail archiving modules - I wanted it to be possible for third-parties to add
plugin modules to archive information they were interested in, and have
their
plugins feature as first-class members of the Email::Store system.
I identified three things which could make this happen: embedded SQL, so
that
modules could define their own tables, provided by Class::DBI::DATA::Schema;
a plugin loader for modules, provided by Module::Pluggable; and a pipelined
system of trigger points, so that plugins could influence each other's
behaviour, provided by what became Module::Pluggable::Ordered.
Further, I needed Class::DBI::DATA::Schema's translation option so that the
same schema code could work no matter what the database.
For my next Maypole project, I needed the same style of pluggability, and
realised that this three-way pluggability approach works equally well for
Maypole classes. By tying the three techniques into Maypole, I created a
Maypole-based framework that "stretches" in all directions - vertically with
the simple addition of new actions, and horizontally with the simple
addition
of completely new classes. The "stretchy" result is called Rubberband, and
it's available from CPAN.
Here's an example of how I'm currently using Rubberband. I'm developing a
blogging tool called Feuilleton. It has certain "core" concepts: blogs,
posts,
users, and so on. It then has "plugin" concepts: comments, blogrolls.
Here's what Feuilleton.pm currently looks like:
package Feuilleton;
use Rubberband (
dsn => "dbi:mysql:feuilleton",
search_path => [qw( Feuilleton::Core Feuilleton::Plugin )],
translate_sql_from => "mysql"
);
Feuilleton->config->{auth}{user_class} = "Feuilleton::Core::User";
Feuilleton->config->{base_url} = "http://localhost/feuilleton/";
Feuilleton->config->{template_root} =
"/Users/simon/maypole-stuff/feuilleton/templates";
sub fresh_start {
Feuilleton->create_database_tables();
Feuilleton->call_plugins("on_create_database");
}
Unlike Maypole::Model::CDBI, Rubberband doesn't (by default) look at the
database to load its classes, but looks at the plugin modules: the
"search_path" line tells it to load up all of Feuilleton::Core::* and
Feuilleton::Plugin::* and use them as Maypole classes *if* they are attached
to a database table. "translate_sql_from" describes the data language that
the SQL schema is going to be written in. Rubberband provides
"create_database_tables", which runs the SQL statements embedded in every
module, and "call_plugins", which fires off a trigger point. All will become
clear when you see Feuilleton::Core::Blog:
package Feuilleton::Core::Blog;
use strict;
__PACKAGE__->table("blog");
__PACKAGE__->columns(All => qw[id name]);
sub view :Exported { }
sub on_create_database_order { 1 }
sub on_create_database {
Feuilleton::Core::Blog->create({ name => "My new blog" });
}
__DATA__
CREATE TABLE blog (
id integer not null primary key auto_increment,
name varchar(255)
);
When we call "Feuilleton->fresh_start", the "CREATE TABLE blog" statement
is translated from mysql SQL to the local SQL, (which currently happens
to be mysql, but the value of "dsn" will change) and then executed, along
with any other SQL statements in data sections. "Blog" just happens to
be core, but the distinction between core and plugin is deliberately
minimal.
Next, the "on_create_database" subroutines are collated from all plugin
modules, and sorted by the "on_create_database_order" of each class, and
then run in turn; this allows all the plugins to take their turns at setting
up the data they need when the application is started.
Rubberband is still very much in the early stages of development, and
just like with Maypole itself, things change as I work out the easiest and
best ways of working with it, but if you're brave, you've got time, and are
prepare to mess about on your own without expecting much in the way of
support or documentation ;-) then grab it from CPAN and give it a look.
I think it's the new way of creating extensible web applications, and I
like it a lot.
--
<deus_x> Anyone who takes words on the screen personally should not be on
IRC.
_______________________________________________
maypole mailing list
maypole@lists.netthink.co.uk
http://lists.netthink.co.uk/listinfo/maypole
***********************************************************************************
The Royal Bank of Scotland plc. Registered in Scotland No 90312. Registered Office: 36 St Andrew Square, Edinburgh EH2 2YB.
Authorised and regulated by the Financial Services Authority
This e-mail message is confidential and for use by the
addressee only. If the message is received by anyone other
than the addressee, please return the message to the sender
by replying to it and then delete the message from your
computer. Internet e-mails are not necessarily secure. The
Royal Bank of Scotland plc does not accept responsibility for
changes made to this message after it was sent.
Whilst all reasonable care has been taken to avoid the
transmission of viruses, it is the responsibility of the recipient to
ensure that the onward transmission, opening or use of this
message and any attachments will not adversely affect its
systems or data. No responsibility is accepted by The Royal
Bank of Scotland plc in this regard and the recipient should carry
out such virus and other checks as it considers appropriate.
Visit our websites at:
http://www.rbs.co.uk/CBFM
http://www.rbsmarkets.com
********************************************************************************