RFC Class::AppendMethods

In response to Installing chained methods I created Class::AppendMethods. I'd like to get any general feedback on the module prior to uploading it to CPAN. I'm requesting any suggestions regarding API, coding style or the method used to solve this problem (or even the module name if you feel like it). The module consists of a single subroutine which has the job of either copying a code reference into a slot or if something is already present - installing a wrapper to ensure both the new and old methods are called.

Class::AppendMethods

package Class::AppendMethods; use strict; use warnings; use vars qw(@ISA @EXPORT_OK $VERSION %METHODS); require Exporter; @ISA = qw(Exporter); @EXPORT_OK = qw(append_method); $VERSION = '0.01'; sub append_method { my $method_name = shift; my $method_to_install = shift; no strict 'refs'; no warnings 'redefine'; # If I was given a method name then fetch the code # reference from the named slot unless (ref $method_to_install ) { # symref $method_to_install = \&{$method_to_install}; } # Track the list of references to install unless (exists $METHODS{$method_name}) { $METHODS{$method_name} = []; } my $pre_existing_methods = $METHODS{$method_name}; push @$pre_existing_methods, $method_to_install; # Install the new methods if (*{$method_name}{CODE}) { # If the pre-existing method isn't in the local cache then cop +y it over # first. unless (grep $_ == *{$method_name}{CODE}, @$pre_existing_metho +ds) { unshift @$pre_existing_methods, *{$method_name}{CODE}; } # Already existing method *{$method_name} = sub { $_[0]->$_( @_[1 .. $#_] ) for @$pre_existing_methods; }; } else { # Single method - no special calling *{$method_name} = $method_to_install; } # Return the method as a convenience (for who knows what, I don't +know) return *{$method_name}{CODE}; } 1; __END__ =head1 NAME Class::AppendMethods - Install multiple methods into a single slot =head1 SYNOPSIS use Class::AppendMethods 'append_method'; # This installs both versioning_hook and auditing_hook into the # method Object::pre_insert. for my $hook (qw(versioning auditing)) { append_method( 'Object::pre_insert', "${hook}_hook" ); } sub versioning_hook { ... } sub auditing_hook { ... } =head1 DESCRIPTION This allows you to install more than one method into a single method n +ame. I created this so I could install both versioning and auditing hooks i +nto another module's object space. So instead of creating a single larger +method which incorporates the functionality of both hooks I created C<Class::AppendMethods::append_method> to install a wrapper method as +needed. If only one method is ever installed into a space, it is installed dir +ectly with no wrapper. If you install more than one then C<append_method> cr +eates a wrapper which calls each of the specified methods in turn. =head1 PUBLIC METHODS =over 4 =item append_method append_method( $method_name, $method ); This function takes two parameters - the fully qualified name of the m +ethod to install into and the method to install. C<$method_name> must be the fully qualified method name. This means th +at for the method C<pre_insert> of a C<Foo::Bar> object you must pass in C<'Foo::Bar::pre_insert'>. C<$method> may be either a code reference or the fully qualified name +of the method to use. =back =head2 EXAMPLES =over 4 =item Example 1 use Class::AppendMethods 'append_method'; # This installs both versioning_hook and auditing_hook into the # method Object::pre_insert. for my $hook (qw(versioning auditing)) { append_method( 'Object::pre_insert', "${hook}_hook" ); } sub versioning_hook { ... } sub auditing_hook { ... } =item Example 2 use Class::AppendMethods 'append_method'; my @versioned_tables = ( .... ); my @audited_tables = ( .... ); for my $table_list ( { tables => \ @versioned_tables, prefix => 'versioned' }, { tables => \ @audited_tables, prefix => 'audited' } ) { my $tables = $table_list->{'tables'}; my $prefix = $table_list->{'prefix'}; for my $table ( @$tables ) { for my $hook ( qw[pre_insert pre_update pre_delete]) { my $method_name = "GreenPartyDB::Database::${table}::${ho +ok}"; my $method_inst = __PACKAGE__ . "::${prefix}_${hook}"; append_method( $method_name, $method_inst ); } } } sub versioned_pre_insert { ... } sub versioned_pre_update { ... } sub versioned_pre_delete { ... } sub audited_pre_insert { ... } sub audited_pre_update { ... } sub audited_pre_delete { ... } =back =head2 EXPORT This class optionally exports the C<append_method> function. =cut

In reply to RFC Class::AppendMethods by diotalevi

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.