perlautoloadmoosemethod-modifier

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


I have a very interesting predicament. I am working on a Perl script interface to the CVS repository and have created Perl Objects to represent Modules,Paths, and Files. Since Modules, Paths, and Files can all have CVS commands issued on them, I set up the AUTOLOAD routine to take any unidentified methods and issue them on the object as if they were CVS commands.

All of these CVS commands are executed exactly the same way, but some of them need special processing done with the output to get the result i desire.


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

I am using Moose, so typically this special processing could be done as follows:

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

The problem is... I never explicitly created the diff method since it is being generated by AUTOLOAD and Perl won't let me create a method modifier for it since it technically doesn't exist!

Is there a way to get this to work how I want?


Solution

  • Apply after to your AUTOLOAD method.

    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 I may want even more control over the diff command so I have added more detail to your answer. Hopefully someone will find this information useful.

    For even more control you can use 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(@_);
        }
    };
    

    This allows you to do special processing before the function is called AND after.

    For more information see: Moose::Manual::MethodModifiers