my $cache_key;
if ($cache_ok) {
$cache_key = $class->_anon_cache_key(%options);
+ undef $cache_ok if !defined($cache_key);
+ }
+ if ($cache_ok) {
if (defined $ANON_PACKAGE_CACHE{$cache_key}) {
return $ANON_PACKAGE_CACHE{$cache_key};
}
sub _anon_cache_key {
my $class = shift;
my %options = @_;
- # Makes something like Super::Class|Super::Class::2=Role|Role::1
- return join '=' => (
- join( '|', @{ $options{superclasses} || [] } ),
- join( '|', sort @{ $options{roles} || [] } ),
+
+ my $superclass_key = join('|',
+ map { $_->[0] } @{ Data::OptList::mkopt($options{superclasses} || []) }
);
+
+ my $roles = Data::OptList::mkopt(($options{roles} || []), {
+ moniker => 'role',
+ val_test => sub { ref($_[0]) eq 'HASH' },
+ });
+
+ my @role_keys;
+ for my $role_spec (@$roles) {
+ my ($role, $params) = @$role_spec;
+ $params = { %$params } if $params;
+
+ my $key = blessed($role) ? $role->name : $role;
+
+ if ($params && %$params) {
+ my $alias = delete $params->{'-alias'}
+ || delete $params->{'alias'}
+ || {};
+ my $excludes = delete $params->{'-excludes'}
+ || delete $params->{'excludes'}
+ || [];
+ $excludes = [$excludes] unless ref($excludes) eq 'ARRAY';
+
+ if (%$params) {
+ warn "Roles with parameters cannot be cached. Consider "
+ . "applying the parameters before calling "
+ . "create_anon_class, or using 'weaken => 0' instead";
+ return;
+ }
+
+ $key .= '<' . join('+', 'a', join('%', %$alias),
+ 'e', join('%', @$excludes)) . '>';
+ }
+
+ push @role_keys, $key;
+ }
+
+ my $role_key = join('|', @role_keys);
+
+ # Makes something like Super::Class|Super::Class::2=Role|Role::1
+ return join('=', $superclass_key, $role_key);
}
sub reinitialize {
sub _anon_cache_key {
my $class = shift;
my %options = @_;
+
+ # XXX fix this duplication (see MMC::_anon_cache_key
+ my $roles = Data::OptList::mkopt(($options{roles} || []), {
+ moniker => 'role',
+ val_test => sub { ref($_[0]) eq 'HASH' },
+ });
+
+ my @role_keys;
+ for my $role_spec (@$roles) {
+ my ($role, $params) = @$role_spec;
+ $params = { %$params };
+
+ my $key = blessed($role) ? $role->name : $role;
+
+ if ($params && %$params) {
+ my $alias = delete $params->{'-alias'}
+ || delete $params->{'alias'}
+ || {};
+ my $excludes = delete $params->{'-excludes'}
+ || delete $params->{'excludes'}
+ || [];
+ $excludes = [$excludes] unless ref($excludes) eq 'ARRAY';
+
+ if (%$params) {
+ warn "Roles with parameters cannot be cached. Consider "
+ . "applying the parameters before calling "
+ . "create_anon_class, or using 'weaken => 0' instead";
+ return;
+ }
+
+ $key .= '<' . join('+', 'a', join('%', %$alias),
+ 'e', join('%', @$excludes)) . '>';
+ }
+
+ push @role_keys, $key;
+ }
+
# Makes something like Role|Role::1
- return join '=' => (
- join( '|', sort @{ $options{roles} || [] } ),
- );
+ return join('|', @role_keys);
}
#####################################################################
use metaclass;
use Scalar::Util 'blessed';
+use List::MoreUtils 'all';
use base 'Moose::Meta::Role::Application';
my $class = $obj_meta->create_anon_class(
superclasses => [ blessed($object) ],
roles => [ $role, keys(%$args) ? ($args) : () ],
- cache => 1,
+ cache => (all { $_ eq '-alias' || $_ eq '-excludes' } keys %$args),
);
$class->rebless_instance( $object, %{ $self->rebless_params } );