I'm trying to stick to the published API to dynamically modify methods in Moo
, and have not come up with a general solution.
First off, some code:
package R1 {
use Moo::Role;
sub r1 { say __PACKAGE__ }
}
package C1 {
use Moo;
sub c1 { say __PACKAGE__ }
}
use Scalar::Util qw[ blessed ];
use Moo::Role ();
my $c = C1->new;
Moo::Role->apply_roles_to_object( $c, 'R1' );
The role application will illustrate a failure in one approach.
I've tried two approaches.
The first uses Class::Method::Modifiers:
use Class::Method::Modifiers qw[ install_modifier ];
install_modifier( blessed( $c ),
before => r1 =>
sub { say "BEFORE r1" }
);
$c->r1;
and works fine:
% perl test.pl
BEFORE r1
R1
The code for Moo
's internal _install_modifier
subroutine is very similar, but also performs additional Moo
specific actions, so this approach is not exactly equivalent.
The next approach I tried was to directly use the before
modifier available to $c
, and thus get the additional Moo
special sauce:
$c->can('before')->( r1 => sub { say "BEFORE r1" } );
$c->r1;
But...
% perl test.pl
The method 'r1' is not found in the inheritance hierarchy for class C1 at [...]/lib/site_perl/5.28.0/Class/Method/Modifiers.pm line 42.
Class::Method::Modifiers::install_modifier("C1", "before", "r1") called at /[...]/lib/site_perl/5.28.0/Moo/_Utils.pm line 44
Moo::_Utils::_install_modifier("C1", "before", "r1", CODE(0x5590bb800360)) called at [...]/lib/site_perl/5.28.0/Moo.pm line 84
Moo::before("r1", CODE(0x5590bb800360)) called at test.pl line 25
It seems that modifiers were generated for the original C1
class, and not updated when the R1
role was applied. The following egregious hack "fixes" that:
use Import::Into;
Moo->import::into( blessed $c );
$c->can('before')->( r1 => sub { say "BEFORE r1" } );
$c->r1;
which results in:
% perl test.pl
BEFORE r1
R1
So, is there a means of achieving my goal using only the published Moo
API?
Thanks!