I'm using Moose and I need to wrap method calls in my project. It's important that my wrapping code be the most outer modifier. What I've done so far is put my method modifiers in a Moose Role and then applied that role at the end of my class like this:
use Moose::Util;
Moose::Util::apply_all_roles(__PACKAGE__->meta, ('App:Roles::CustomRole'));
__PACKAGE__->meta->make_immutable;
This allows me to be reasonably sure that my my role's modifiers are defined last, therefore giving me the correct behavior for "before" and "after." (The "before" and "after" in the role are called very first and very last.)
I originally thought this would be sufficient, but I now really need to wrap methods in a similar way with "around." Class::MOP, which Moose is built on, applies "around" modifiers very first, therefore they're called after "before" and before "after."
For more detail, here is the current calling order of my modifiers:
CUSTOM ROLE before
before 2
before 1
CUSTOM ROLE around
around
method
around
CUSTOM ROLE around
after 1
after 2
CUSTOM ROLE AFTER
I really need something like this:
CUSTOM ROLE before
CUSTOM ROLE around
before 2
before 1
around
method
around
after 1
after 2
CUSTOM ROLE around
CUSTOM ROLE AFTER
Any ideas on how to get my "around" modifier to be applied / called where I want it to? I know I could do some symbol table hacking (like Class::MOP is already doing) but I'd really rather not.
Simplest solution is to have CUSTOM ROLE define a method that calls the main method and then wrap that.
role MyRole {
required 'wrapped_method';
method custom_role_base_wrapper { $self->wrapped_method(@_) }
around custom_role_base_wrapper { ... }
before custom_role_base_wrapper { ... }
}
The problem you're having is that you're trying to have the CUSTOM ROLE around wrap something other than a method. Which is not what it is designed to do. Other than writing similar symbol table hackery like you've suggested (probably you could argue one of the Moose people into exposing an API in Class::MOP to help get there), the only other solution I can think of is the one above.
If you don't want the extra call stack frame that custom_role_base_wrapper
will add, you should look at Yuval's Sub::Call::Tail
or using goto
to manipulate the call stack.
I'm fairly new to Moose, but why do you do this:
use Moose::Util;
Moose::Util::apply_all_roles(__PACKAGE__->meta, ('App:Roles::CustomRole'));
rather than simply this?
with 'App:Roles::CustomRole';
Regarding your question, it's a bit of a hack, but could you split your around
method into before
and after
methods and apply the role at the end of your class definition (so it is applied in your desired order)? You could use private attributes to save state between the two methods if absolutely necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With