1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
NAME
Role::Hooks - role callbacks
SYNOPSIS
package Local::Role {
use Moo::Role;
use Role::Hooks;
Role::Hooks->after_apply(__PACKAGE__, sub {
my ($role, $target) = @_;
print "$role has been applied to $target.\n";
});
}
package Local::Class {
use Moo;
with "Local::Role"; # prints above message
}
DESCRIPTION
This module allows a role to run a callback when it is applied to a class
or to another role.
Compatibility
It should work with Role::Tiny, Moo::Role, Moose::Role, Mouse::Role,
Role::Basic, and Mite. Not all class builders work well with all role
builders (for example, a Moose class consuming a Mouse role). But when
they do work together, Role::Hooks should be able to run the callbacks.
(The only combination I've tested is Moo with Moose though.)
Some other role implementations (such as Moos::Role, exact::role, and
OX::Role) are just wrappers around one of the supported role builders, so
should mostly work.
With Role::Basic, the `after_apply` hook is called a little earlier than
would be ideal; after the role has been fully loaded and its methods have
been copied into the target package, but before handling `requires`, and
before patching the `DOES` method in the target package. If you are using
Role::Basic, consider switching to Role::Tiny.
With Mite, the `before_apply` hook is called fairly late; after the role
is fully loaded and attributes and methods have been copied into the
target package, after `DOES` has been patched, but before method modifiers
from the role have been applied to the target package.
Apart from Role::Tiny/Moo::Role, a hashref of additional arguments (things
like "-excludes" and "-alias") can be passed when consuming a role.
Although I discourage people from using these in general, if you need
access to these arguments in the callback, you can check
%Role::Hooks::ARGS.
Roles generated via Package::Variant should work; see t/20packagevariant.t
for a demonstration.
Methods
`before_apply`
Role::Hooks->before_apply($rolename, $callback);
Sets up a callback for a role that will be called before the role is
applied to a target package. The callback will be passed two
parameters: the role being applied and the target package.
The role being applied may not be the same role as the role the
callback was defined in!
package Local::Role1 {
use Moo::Role;
use Role::Hooks;
Role::Hooks->before_apply(__PACKAGE__, sub {
my ($role, $target) = @_;
print "$role has been applied to $target.\n";
});
}
package Local::Role2 {
use Moo::Role;
with "Local::Role1";
}
package Local::Class1 {
use Moo::Role;
with "Local::Role2";
}
This will print:
Local::Role1 has been applied to Local::Role2.
Local::Role2 has been applied to Local::Class1.
If you only care about direct applications of roles (i.e. the first
one):
Role::Hooks->before_apply(__PACKAGE__, sub {
my ($role, $target) = @_;
return if $role ne __PACKAGE__;
print "$role has been applied to $target.\n";
});
If you only care about roles being applied to classes (i.e. the second
one):
Role::Hooks->before_apply(__PACKAGE__, sub {
my ($role, $target) = @_;
return if Role::Hooks->is_role($target);
print "$role has been applied to $target.\n";
});
`after_apply`
Role::Hooks->after_apply($rolename, $callback);
The same as `before_apply`, but called later in the role application
process.
Note that when the callback is called, even though it's after the role
has been applied to the target, it doesn't mean the target has
finished being built. For example, there might be `has` statements
after the `with` statement, and those will not have been evaluated
yet.
If you want to throw an error when someone applies your role to an
inappropriate target, it is probably better to do that in
`before_apply` if you can.
`after_inflate`
Role::Hooks->after_inflate($pkg_name, $callback);
Even though this is part of Role::Hooks, it works on classes too. But
it only works on classes and roles built using Moo. This runs your
callback if your Moo class or role gets "inflated" to a Moose class or
role.
If you set up a callback for a role, then the callback will also get
called if any packages that role was applied to get inflated.
`is_role`
Will return true if the given package seems to be a role, false
otherwise.
(In fact, returns a string representing which role builder the role
seems to be using -- "Role::Tiny", "Moose::Role", "Mouse::Role",
"Role::Basic", or "Mite::Role"; roles built using Moo::Role are
detected as "Role::Tiny".)
ENVIRONMENT
The environment variable `PERL_ROLE_HOOKS_DEBUG` may be set to true to
enable debugging messages.
BUGS
Please report any bugs to
<http://rt.cpan.org/Dist/Display.html?Queue=Role-Hooks>.
SEE ALSO
Role::Tiny, Moose::Role.
AUTHOR
Toby Inkster <tobyink@cpan.org>.
COPYRIGHT AND LICENCE
This software is copyright (c) 2020-2022 by Toby Inkster.
This is free software; you can redistribute it and/or modify it under the
same terms as the Perl 5 programming language system itself.
DISCLAIMER OF WARRANTIES
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|