How can I apply a method modifier to a method generated by AUTOLOAD?

I have a very interesting fix. I am working on a Perl script interface in a CVS repository and have created Perl objects for presentation Modules, Pathsand Files. Since Modules, Pathsand Filesmay have CVS commands issued to them, I set up a routine AUTOLOADto accept any unidentified methods and release them on the object, as if they were CVS commands.

All of these CVS commands are executed in exactly the same way, but some of them need special processing performed with the exit to get the desired result.


For example, I want to take the output from the diff command and reformat it before I return it.

I use Moose, so usually this special processing can be done as follows:

after 'diff' => sub {
    # Reformat output here
}

The problem is that I never explicitly created a method diff, since it is generated AUTOLOAD, and Perl does not allow me to create a method modifier for it, because it does not technically exist!

Is there a way to make this work as I want?

+4
source share
3 answers

Apply afterto your method AUTOLOAD.

after 'AUTOLOAD' => sub {
    my $method = $The::Package::AUTOLOAD;
    $method =~ s/.*:://;
    if ($method eq 'diff') {
        # do  after diff  stuff
    } elsif ($method eq 'foo') {
        # do  after foo  stuff
    } else {
        # never mind, don't want to do anything after this function
    }
};

EDIT:

I found that more control over the team might be required diff, so I added more details to your answer. Hope someone finds this information helpful.

around!

around 'AUTOLOAD' => sub {
    my $orig = shift;
    my $self = shift;
    (my $command = $AUTOLOAD) =~ s{.+::}{};

    # Special processing
    if ($command eq 'diff') {

        #
        # Add "before" special processing here
        #

        my $output = $self->$orig(@_);

        #
        # Add "after" special processing here
        #

    }
    else {
        return $self->$orig(@_);
    }
};

, .

. Moose:: Manual:: MethodModifiers

+3

, AUTOLOAD -using, , can can , .

__PACKAGE__->can( "diff" );
after diff => sub { ... };
0

, , , AUTOLOAD. , , .

, , - :

package Trait::CVSActions;

use Moose::Role;

sub commit { print 'in commit for ' . shift . "\n" }

sub diff { print 'diffing for ' . shift . "\n" }

package Module;

use Moose;

with 'Trait::CVSActions';

package Path;

use Moose;

with 'Trait::CVSActions';

after commit => sub { print "after commit on Path\n" };

package main;

my $module = new Module;
my $path = new Path;

$module->commit;
$path->commit;

If you want to use AUTOLOAD to send to unknown commands, this is dangerous, as there may be some that you will have to have special processing that you are not aware of, so you yourself may face future problems.

0
source

Source: https://habr.com/ru/post/1607018/


All Articles