I think the simplest solution for plugins to work like C::A::ValidateRM does. I don't think the proposed base class really
Mark-
I think I prefer your suggestion of using the standard export technique - although I still firmly believe that separate namespaces are essential.
However, I'm unclear on how Exporter works in an object oriented context. How does check_rm get into the $self object below?
From CGI::Application::ValidateRM:
sub form_process {
my $self = shift;
use CGI::Application::ValidateRM;
my ($results, $err_page) =
$self->check_rm('form_display','_form_profile');
return $err_page if $err_page; ...
}
Here is a restatement of our requirements from earlier discussion: 1) a separate name space for each plugin 2) plugins must be able to discover and use other plugins 3) allow object caching by plugins
1) I'm now leaning in the direction of not needing a separate namespace for each plugin as long as each plugin will have a store in the application object. This would be solved by the suggestion that a plugin for incorporating 'Foo::Bar' would use $self->{'Foo::Bar'}.
Maybe if you could think of a case where separate namespaces for plugins would be essential it would help.
Also, if we use Mark's idea of simply using Exporter then the user can still turn off methods he doesn't want to use, just like with any other module using Exporter. So if you override 'load_tmpl' in you plugin but the user doesn't want it to override his method, but still wants to use other methods that your plugin provides, it's very easy to do.
2) If we follow the naming convention repeated above, this would solve it. If an auth plugin wanted to access a 'Session' plugin, then he could use $self->{'Session'} or $self->session.
3) Once again, this is solved by the above.
I think the solution I'm going to try implementing looks like this:
In C::A::MyApp or C::A::AppBase:
use C::A::Plugin::MyPlugin( name => myname, exported => 0|1 );
Here, name attribute (UID) is optional, and a universally unique name (UID) will be provided by default.
Here's what will happen:
$self is a C::A object or child thereof.
$self->{_plugins}{UID}{ ref => $plugin_object, exported => 0|1 ...}
Where exported equals 1, exported methods will be available as follows:
$self->pub_method;
Plugins can discover each other by looking at all
plugins on $self->{_plugins} and check their ref
types.
Singleton plugins will be responsible for makeing themselves singletons.
Plugin authors will inherit from base class
C::A::Plugin which will provide exporting functions
and a DESTROY method that will keep $self->{_plugins}
synchronized with plugin object destruction. If this
synchronizing method is problematic, the 'ref' hash
key above might be replaced with a 'idtag' (random ID
number) and 'type' (C::A::Plugin::MyPlugin) attributes
which will be deleted when the associated plugin
object is destroyed. (I've heard of linking these
kinds of things with tie, but I don't want to use
tie.)
Just seems too complicated for such a simple issue. But maybe that's just me.
helps this. It just does the exporting in a different way. It uses attributes to do this, which are less well known than the standard EXPORT method.
I don't think it's too much of ask of plugin writers to use standard Exporter techniques-- export public routines and hide private ones.
I'm starting to agree with Mark here.
I propose the following alternate solution.
1. Rename and refactor existing plugin modules to be consistent: - ::Session - ::ValidateRM - ::Config::Simple - ::TT
Sounds good.
Thoughts?
I still think we should put 'Plugin' in the object's name. There are many modules out there that split their work up into several classes that are a part of the same distribution. All of these helper classes exist under the same namespace as the original (Class::DBI has Class::DBI::Column, Class::DBI::Iterator, Class::DBI::Relationship, etc and TT does the same thing).
I think it might be misleading to have these plugin directly under the CGI::Application namespace since they aren't used by C::A but by the user. By putting them in a Plugin namespace then there is no confusion. This is also what Class::DBI and TT do and they are very successful in attracting users.
>>2. Simply update the POD of CGI::Application to
explain what's going on, both for users and writers of plugins. Something like this:
=head1 PLUG-INS
CGI::Application has a plug-in architecture that is easy to use and easy to develop new plug-ins for.
=head2 Existing plug-ins
Here are some plug-ins that have already been developed for CGI::Application. For a current complete list, please consult CPAN:
http://search.cpan.org/search?query=Class%3A%3ADBI%3A%3APlugin&mode=module
=over 4
=item *
L<CGI::Application::Plugin::Session> - Integration with L<CGI::Session>
=item *
L<CGI:::Application::Plugin::ValidateRM> - Integration with Data::FormValidator and HTML::FillInForm
=item *
L<CGI::Application::ValidateRM::TT> - Use L<Template::Toolkit> as an alternative to HTML::Template.
=item *
L<CGI::Application::Plugin::Config::Simple> - Integration with Config::Simple.
=back
Consult each plug-in for the exact usage syntax.
=head2 Writing Plug-ins
Writing plug-ins is simple. Simply create a new package, and export the methods that you want to become part of a CGI::Application project. See L<CGI::Application::Plugin::ValidateRM> for an example.
You only need to keep in mind that your extension should "play well with others". The method names exported should be unique. Also, additions to the CGI::Application object should be designed not to conflict with other potentional plug-ins. For that reason, it's recommended that you add a a hash key to the CGI::Application which reflects the name of your plug-in, such as:
$self->{'Config::Simple'}
###########
Thoughts?
The above pod would work for me except for a blurb about naming your plugin in the C::A::Plugin namespace :)
-- Michael Peters Developer Plus Three, LP
-- Michael Peters Developer Plus Three, LP
--------------------------------------------------------------------- Web Archive: http://www.mail-archive.com/[EMAIL PROTECTED]/ http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2 To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]