return $class;
}
+my %ANON_CLASSES;
+
+sub create_anon_class {
+ my ($self, %options) = @_;
+
+ my $cache_ok = delete $options{cache};
+
+ my @superclasses = sort @{$options{superclasses} || []};
+ my @roles = sort @{$options{roles} || []};
+
+ # something like Super::Class|Super::Class::2=Role|Role::1
+ my $cache_key = join '=' => (
+ join('|', @superclasses),
+ join('|', @roles),
+ );
+
+ if($cache_ok && defined $ANON_CLASSES{$cache_key}){
+ return $ANON_CLASSES{$cache_key};
+ }
+
+ my $new_class = $self->SUPER::create_anon_class(%options);
+
+ if($cache_ok){
+ $ANON_CLASSES{$cache_key} = $new_class;
+ }
+
+ return $new_class;
+}
+
sub add_role {
my ($self, $role) = @_;
(blessed($role) && $role->isa('Moose::Meta::Role'))
die 'DEPRECATED: use Moose::Util::apply_all_roles($meta, @roles) instead'
}
-my %ANON_CLASSES;
-
sub _process_attribute {
my $self = shift;
my $name = shift;
}
if ($options{traits}) {
-
- my $anon_role_key = join "|" => @{$options{traits}};
-
- my $class;
- if (exists $ANON_CLASSES{$anon_role_key} && defined $ANON_CLASSES{$anon_role_key}) {
- $class = $ANON_CLASSES{$anon_role_key};
- }
- else {
- $class = Moose::Meta::Class->create_anon_class(
- superclasses => [ $attr_metaclass_name ]
- );
- $ANON_CLASSES{$anon_role_key} = $class;
-
- my @traits;
- foreach my $trait (@{$options{traits}}) {
- eval {
- my $possible_full_name = 'Moose::Meta::Attribute::Custom::Trait::' . $trait;
- Class::MOP::load_class($possible_full_name);
- push @traits => $possible_full_name->can('register_implementation')
- ? $possible_full_name->register_implementation
- : $possible_full_name;
- };
- if ($@) {
- push @traits => $trait;
- }
+ my @traits;
+ foreach my $trait (@{$options{traits}}) {
+ eval {
+ my $possible_full_name = 'Moose::Meta::Attribute::Custom::Trait::' . $trait;
+ Class::MOP::load_class($possible_full_name);
+ push @traits => $possible_full_name->can('register_implementation')
+ ? $possible_full_name->register_implementation
+ : $possible_full_name;
+ };
+ if ($@) {
+ push @traits => $trait;
}
-
- Moose::Util::apply_all_roles($class, @traits);
}
+ my $class = Moose::Meta::Class->create_anon_class(
+ superclasses => [ $attr_metaclass_name ],
+ roles => [ @traits ],
+ cache => 1,
+ );
+
$attr_metaclass_name = $class->name;
}
-
+
return $attr_metaclass_name->new($name, %options);
}
}
=item B<create>
-Like C<< Class::MOP->create >> but accepts a list of roles to apply to
+Overrides original to accept a list of roles to apply to
the created class.
+ my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
+
+=item B<create_anon_class>
+
+Overrides original to support roles and caching.
+
+ my $metaclass = Moose::Meta::Class->create_anon_class(
+ superclasses => ['Foo'],
+ roles => [qw/Some Roles Go Here/],
+ cache => 1,
+ );
+
=item B<make_immutable>
Override original to add default options for inlining destructor
--- /dev/null
+use strict;
+use warnings;
+use Test::More tests => 11;
+
+BEGIN {
+ use_ok('Moose::Meta::Class');
+ use_ok('Moose');
+ use_ok('Moose::Role');
+}
+
+{
+ package Class;
+ use Moose;
+
+ package Foo;
+ use Moose::Role;
+ sub foo_role_applied { 1 }
+
+ package Bar;
+ use Moose::Role;
+ sub bar_role_applied { 1 }
+}
+
+# try without caching first
+
+{
+ my $class_and_foo_1 = Moose::Meta::Class->create_anon_class(
+ superclasses => ['Class'],
+ roles => ['Foo'],
+ );
+
+ my $class_and_foo_2 = Moose::Meta::Class->create_anon_class(
+ superclasses => ['Class'],
+ roles => ['Foo'],
+ );
+
+ isnt $class_and_foo_1->name, $class_and_foo_2->name,
+ 'creating the same class twice without caching results in 2 classes';
+
+ map { ok $_->name->foo_role_applied } ($class_and_foo_1, $class_and_foo_2);
+}
+
+# now try with caching
+
+{
+ my $class_and_foo_1 = Moose::Meta::Class->create_anon_class(
+ superclasses => ['Class'],
+ roles => ['Foo'],
+ cache => 1,
+ );
+
+ my $class_and_foo_2 = Moose::Meta::Class->create_anon_class(
+ superclasses => ['Class'],
+ roles => ['Foo'],
+ cache => 1,
+ );
+
+ is $class_and_foo_1->name, $class_and_foo_2->name,
+ 'with cache, the same class is the same class';
+
+ map { ok $_->name->foo_role_applied } ($class_and_foo_1, $class_and_foo_2);
+
+ my $class_and_bar = Moose::Meta::Class->create_anon_class(
+ superclasses => ['Class'],
+ roles => ['Bar'],
+ cache => 1,
+ );
+
+ isnt $class_and_foo_1->name, $class_and_bar,
+ 'class_and_foo and class_and_bar are different';
+
+ ok $class_and_bar->name->bar_role_applied;
+}