Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the MooseX-ClassCompositor CPAN distribution.

Report information
The Basics
Id: 76176
Status: resolved
Priority: 0/
Queue: MooseX-ClassCompositor

People
Owner: Nobody in particular
Requestors: perl [...] toby.ink
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in:
  • 0.001
  • 0.002
  • 0.003
  • 0.004
Fixed in: (no value)



Subject: Roles which require methods cannot be composed
Given a role like: { package MyRole; use Moose::Role; has monkeys => (is => 'rw'); requires 'bananas'; } It will throw when you try to compose it with MXCC unless you also compose a role that implements bananas. The attached patch (and test case) provides a simple solution for this problem.
Subject: mxcc.t
{ package MyRole; use Moose::Role; has monkeys => (is => 'rw'); requires 'bananas'; } use MooseX::ClassCompositor; use Test::More tests => 3; my $comp = MooseX::ClassCompositor->new( class_basename => 'MyClass', ); my $class = $comp->class_for( { bananas => sub { 'yellow ones' } }, 'MyRole', ); my $inst = $class->new(monkeys => 1); ok($inst->DOES('MyRole'), "$class\->does('MyRole')"); can_ok($inst => 'bananas'); can_ok($inst => 'monkeys');
Subject: mxcc.diff
--- /usr/lib/perl5/site_perl/5.10.1/MooseX/ClassCompositor.pm 2012-02-14 21:46:00.000000000 +0000 +++ MooseX/ClassCompositor.pm 2012-03-30 21:31:20.806043797 +0100 @@ -98,11 +98,14 @@ # $role_hash is a hash mapping nonce-names to role objects # $role_names is an array of names of more roles to add - my (@roles, @role_class_names, @all_names); + my (@roles, @role_class_names, @all_names, %subs); while (@args) { my $name = shift @args; - if (ref $name) { + if (ref $name eq 'HASH') { + $subs{$_} = $name->{$_} for keys %$name; + next; + } elsif (ref $name eq 'ARRAY') { my ($role_name, $moniker, $params) = @$name; my $full_name = $self->_rewrite_roles($role_name); @@ -140,6 +143,7 @@ my $class = Moose::Meta::Class->create( $name => ( superclasses => [ 'Moose::Object' ], + methods => { %subs }, )); $class = Moose::Util::MetaRole::apply_metaroles( @@ -164,7 +168,11 @@ my @k; while (@args) { my $arg = shift @args; - if (ref $arg) { + if (ref $arg eq 'HASH') { + push @k, + map { sprintf('FUNC(%s): { %s }', $_, refaddr($arg->{$_})) } + sort keys %$arg; + } elsif (ref $arg eq 'ARRAY') { my ($role_name, $moniker, $params) = @$arg; push @k, "$moniker : { " . __hash_to_string($params) . " }"; } else { @@ -298,6 +306,14 @@ Note that at present, passing Moose::Meta::Role objects is B<not> supported. This should change in the future. +Additional methods that the class should provide may be passed as a hashref. +This allows any methods required by the role to be implemented. + + my $class = $compositor->class_for( + 'Role::Name', + { my_method => sub { ... } }, + ); + =head1 THANKS Thanks to Pobox.com for sponsoring the development of this library.
On 2012-03-30 17:15:40, TOBYINK wrote: Show quoted text
> The attached patch (and test case) provides a simple solution for this > problem.
My fundamental problem with this approach is that it breaks the reproducibility of the composition from the memoization table. In the other cases, you can take the memoization table, save it to a file, and later reconstruct the classes that had been composed. I'd rather not bake into MXCC something that breaks that assumption. What if, instead, you used a little role() routine that built an anonymous role as needed with the provided methos. It would require no changes to MXCC and might have plenty of other uses. Thoughts? Also, I apologize for the ridiculous delay in my reply. I've had this ticket flagged for reply for too long, and there's no excuse. I just failed to get off my duff. :-( -- rjbs
For some reason it's not working. ``` use strict; use warnings; use Moose (); use MooseX::ClassCompositor (); sub methods { my $r = Moose::Meta::Role->create_anon_role( methods => ( ref $_[0] eq 'HASH' ? $_[0] : +{@_} ), ); return $r->name; } my @roles = ( methods( true => sub { print "true\n" } ), methods( false => sub { print "false\n" } ), ); my $class = MooseX::ClassCompositor->new(class_basename => 'My')- Show quoted text
>class_for(@roles);
my $object = $class->new; ($object->can('true') && $object->can('false')) ? $object->true : $object->false; ``` Class::MOP::load_class appears to be attempting to re-load the role's ".pm" file from disk (which of course doesn't exist). Adding a dummy entry to %INC doesn't seem to fix things either. Can't locate Moose/Meta/Role/__ANON__/SERIAL/7.pm in @INC (@INC contains: ...) at .../Module/Runtime.pm line 317. at moose-role.pl line 18. I have up to date versions of Moose, MooseX::ClassCompositor and Class::Load. Perl is 5.16.0.
OK, for some reason I need to create a dummy name for my role. Anonymous roles don't work with MooseX::ClassCompositor... use strict; use warnings; use thanks (); use Moose (); use MooseX::ClassCompositor (); my $anon; sub methods { my $r = Moose::Meta::Role->create( ('This::Is::Not::Really::Anon::Role'.++$anon), methods => ( ref $_[0] eq 'HASH' ? $_[0] : +{@_} ), ); thanks->unimport($r->name); return $r->name; } my @roles = ( methods( true => sub { print "true\n" } ), methods( false => sub { print "false\n" } ), ); Class::MOP::load_class($_) for @roles; my $class = MooseX::ClassCompositor->new(class_basename => 'My')- Show quoted text
>class_for(@roles);
my $object = $class->new; 1 ? $object->true : $object->false;
Subject: Re: [rt.cpan.org #76176] Roles which require methods cannot be composed
Date: Tue, 18 Sep 2012 07:58:25 -0400
To: Toby Inkster via RT <bug-MooseX-ClassCompositor [...] rt.cpan.org>
From: Ricardo Signes <rjbs [...] cpan.org>
* Toby Inkster via RT <bug-MooseX-ClassCompositor@rt.cpan.org> [2012-09-18T04:48:15] Show quoted text
> Queue: MooseX-ClassCompositor > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=76176 > > > OK, for some reason I need to create a dummy name for my role. > Anonymous roles don't work with MooseX::ClassCompositor...
Even "anonymous" roles have names, I think! I'll look into figuring out what the heck is going on, here. It seems pretty weird to me! My only guess is that they don't get put into a package, so the $r object is garbage collected when you just return the name. What if you return the role object, then use its name while $r is still referenced? (Also, I'll try that myself later.) -- rjbs
Download signature.asc
application/pgp-signature 490b

Message body not shown because it is not plain text.

Show quoted text
> My only guess is that they don't get put into a package, > so the $r object is garbage collected when you just return > the name.
Spot on! Class::MOP::Package::DESTROY.
Fork with support for Moose::Meta::Role objects, including anonymous roles. https://github.com/tobyink/MooseX-ClassCompositor The fork includes extra test cases and documentation.
This was merged in 0.005. Thanks! -- rjbs