From: Dave Rolsky Date: Sun, 13 Feb 2011 22:38:05 +0000 (-0600) Subject: Fixed reinitialization bug that lost all role meta info X-Git-Tag: 1.9903~17 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=17c594b1434b5be862add5a10a6bd403f9ee4b5f;p=gitmo%2FMoose.git Fixed reinitialization bug that lost all role meta info --- diff --git a/Changes b/Changes index d8bb65c..880a4b0 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,10 @@ for, noteworthy changes. * Don't initialize lazy attributes with defaults in the constructor (for immutable classes). (mo) + * When reinitializing meta objects for classes and roles, we failed to + preserve roles and role applications. This led to weird bugs. Many MooseX + modules end up reinitializing your class or role. (Dave Rolsky) + 1.9902-TRIAL Mon, Jan 03, 2011 [OTHER] diff --git a/lib/Moose/Meta/Class.pm b/lib/Moose/Meta/Class.pm index 4ad1108..07f5e7e 100644 --- a/lib/Moose/Meta/Class.pm +++ b/lib/Moose/Meta/Class.pm @@ -634,6 +634,24 @@ sub _process_inherited_attribute { } } +# reinitialization support + +sub _restore_metaobjects_from { + my $self = shift; + my ($old_meta) = @_; + + $self->SUPER::_restore_metaobjects_from($old_meta); + + for my $role ( @{ $old_meta->roles } ) { + $self->add_role($role); + } + + for my $application ( @{ $old_meta->_get_role_applications } ) { + $application->class($self); + $self->add_role_application ($application); + } +} + ## Immutability sub _immutable_options { diff --git a/lib/Moose/Meta/Role.pm b/lib/Moose/Meta/Role.pm index 84f0111..7dfe6a5 100644 --- a/lib/Moose/Meta/Role.pm +++ b/lib/Moose/Meta/Role.pm @@ -227,6 +227,10 @@ sub _restore_metaobjects_from { $self->_restore_metamethods_from($old_meta); $self->_restore_metaattributes_from($old_meta); + + for my $role ( @{ $old_meta->get_roles } ) { + $self->add_role($role); + } } sub add_attribute { diff --git a/lib/Moose/Meta/Role/Application/ToClass.pm b/lib/Moose/Meta/Role/Application/ToClass.pm index 28c2ed3..d544f7f 100644 --- a/lib/Moose/Meta/Role/Application/ToClass.pm +++ b/lib/Moose/Meta/Role/Application/ToClass.pm @@ -14,7 +14,7 @@ __PACKAGE__->meta->add_attribute('role' => ( )); __PACKAGE__->meta->add_attribute('class' => ( - reader => 'class', + accessor => 'class', )); sub apply { diff --git a/t/050_metaclasses/060_reinitialize.t b/t/050_metaclasses/060_reinitialize.t index ca34b7d..04d021f 100644 --- a/t/050_metaclasses/060_reinitialize.t +++ b/t/050_metaclasses/060_reinitialize.t @@ -14,12 +14,40 @@ sub check_meta_sanity { isa_ok($meta->get_method('foo'), 'Moose::Meta::Method'); ok($meta->has_attribute('bar')); isa_ok($meta->get_attribute('bar'), 'Moose::Meta::Attribute'); + + if ( $meta->name eq 'Foo' ) { + ok($meta->does_role('Role1'), 'does Role1'); + ok($meta->does_role('Role2'), 'does Role2'); + + is_deeply( + [ + map { [ $_->role->name, $_->class->name ] } + sort { $a->role->name cmp $b->role->name } + $meta->role_applications + ], + [ + [ 'Role1|Role2', 'Foo' ], + ], + 'role applications for Role1 and Role2' + ); + } +} + +{ + package Role1; + use Moose::Role; +} + +{ + package Role2; + use Moose::Role; } { package Foo; use Moose; sub foo {} + with 'Role1', 'Role2'; has bar => (is => 'ro'); } @@ -276,4 +304,18 @@ ok(Quux->meta->has_method('DEMOLISH')); isa_ok(Quux->meta->get_method('DEMOLISH'), 'Moose::Meta::Method'); does_ok(Quux->meta->get_method('DEMOLISH'), 'Foo::Role::Method'); +{ + package Role3; + use Moose::Role; + with 'Role1', 'Role2'; +} + +ok( Role3->meta->does_role('Role1'), 'Role3 does Role1' ); +ok( Role3->meta->does_role('Role2'), 'Role3 does Role2' ); + +Moose::Meta::Role->reinitialize('Role3'); + +ok( Role3->meta->does_role('Role1'), 'Role3 does Role1 after reinitialize' ); +ok( Role3->meta->does_role('Role2'), 'Role3 does Role2 after reinitialize' ); + done_testing;