From: Andrew G. <ag...@bu...> - 2007-08-16 17:28:33
|
Dotan, that looks like what I'm looking for and it's roughly what I had in mind although I didn't realize that a Class::Prototyped class could have multiple parents, which resolves the question of multiple mixins. How are they evaluated for execution? For example, if you override render_enter in Miner::Utils::Links and Miner::Utils::Text, will it just execute both of their render_enter methods in sequence in the order you added their parent slot in the foreach loop of install_mixins? Andrew On 8/16/07 12:44 PM, "Dotan Dimet" <do...@co...> wrote: > Hi Andrew, > > CGI::Prototype as a framework is something of a bit of string lashed > around a set of power tools. > > These tools can do anything you need, but the "framework" provides no > guidance about how to do it, beyond the "with this" inherent in > Randall's choice of tools. > > Instead of 'use base', I use the Class::Prototyped ability to install > other classes into your object. > > > In my base class (CGI::Prototype::Hidden subclass), I've got a method > that installs my plugins: > > > sub install_mixins { > > my ($self, @mixins) = @_; > my $prefix = $self->mixins_prefix . '::'; > foreach my $pkg (@mixins) { > $self->reflect->addSlot ( [ "$pkg*", 'PARENT' ] => $prefix . $pkg ); > my $plugin = $self->reflect->getSlot("$pkg*"); # the mixin we > just installed > } > } > > > The mixins_prefix is "configurable": > > sub mixins_prefix { return "Miner::Utils" } > > > And I install my mixins in app_enter in the base class: > > > sub app_enter { > my ($self) = @_; > # connect to the database: > Foo::DBI::init($Config::Site::database_connect_string, > $Config::Site::schema, $Config::Site::schema); > # load all the Miner::Utils::* packages: > $self->install_mixins(qw(Links Text Cookie Exec Log Order TimeField > LOB )); > } > > > If I want to use a particular mixin only in one or more specific pages, > I call install_mixins in their control_enter or respond_enter methods. > > > My plugin/mixin classes (like Miner::Utils::Cookie, for example) are > CGI::Prototype::Hidden subclasses, although I could probably make them > Class::Prototyped subclasses, or independent modules. > > > The advantage of calling install_mixins in the app_enter is that things > like the CGI object and the database connection are already set up, so I > can install classes that mess about with things like the database > session, like Class::DBI::Plugin::DateFormat::Oracle for example. > > > Hope this helps, > > > - Dotan. > > > > > Andrew Gianni wrote: > >> I'd like to figure out how to get mixins up and running under >> CGI::Prototype. I think I understand the technical aspects of >> Class::Prototyped well enough to pull it off, but I have design questions >> that I'd like feedback on. Assuming all goes well, I'd be happy to >> contribute a CGI::Prototype::Mixin module to CPAN if I can get it that >> generalized. Let me start with three scenarios I'd like to be able to >> address and the issues I see: >> >> 1. We have at least two applications that have pages that allow users to >> upload files. The page is pretty similar in both applications with only a >> few application specific things, like the table it's using and an extra >> field. What I'd like to do is create an abstract page class for the file >> upload page and then implement it with concrete page classes within the >> applications themselves, overriding necessary methods to customize. I have >> actually done this in the past by not giving the abstract class a base class >> and using multiple inheritance in the concrete class like so: >> >> use base qw( Abstract::Page::Class My::App ); >> >> And that mostly works, but I'm knew that it could cause problems down the >> line and after only a few months I found a scenario where it breaks: under >> mod_perl, if I use the mixin page for more than one concrete page class in >> my application and use Apache::Reload to reload the concrete page classes, I >> get errors with whichever concrete page class is reloaded second. I don't >> remember exactly what the error is, but I can look into it if anyone is >> interested. Cracking plugability for this example is most important for me >> because we actually have two more page types that we need to be able to do >> this with and right now they're just duplicated in multiple projects. >> >> 2. I would like to create a pluggable diagnostics module that I could stick >> in front of my app module to override core CGI::P methods at strategic >> locations to capture performance data. >> >> 3. We currently have two different validation methodologies and I'm not sure >> how soon we'll be picking one or the other to standardize on. I'd like to >> create two separate mixin classes so I can choose the validation >> functionality to use. I know I could make this work with something like a >> Strategy pattern, defining two different validation classes with the same >> interface and telling the app which one to use, but if I can get the first >> two examples working, this could easily come along for the ride. >> >> The basics of this from a technical perspective should be pretty straight >> forward, right? I just need to take the mixin class and manipulate it's >> parent and the parent of the class that I want to inherit from it, right? >> >> The complicated part, and perhaps this doesn't have an easy answer, is what >> it I want to insert more than one mixin? What if, for example, >> CGI::Prototype::Hidden became a mixin, as Randal proposed some time ago (did >> I understand that correctly?) and I also have an authentication mixin I'd >> like to use. The problem is that, as a developer, I know the interfaces of >> the two mixins and what they do, but I don't want to have to look at the >> internals of each one to know if I need to put CGI::Prototype::Hidden >> infront of CGI::Prototype::Mixin::Auth or vice versa. Is this actually a >> connundrum or am I overanalyzing this? Any feedback or ideas would be >> appreciated. >> >> Andrew >> >> > -- Andrew Gianni - Lead Programmer Analyst University at Buffalo, State University of New York Computing and Information Technology / Administrative Computing Services 215 MFAC, Ellicott Complex, Buffalo, NY 14261-0026 716.645.5332 - AIM: andrewsgianni - http://www.newkenmore.com/agianni |