Subject: | Loading other MXRP user class in the role{} block causes exception after v1.03 |
Date: | Thu, 17 May 2018 12:41:34 +0000 |
To: | "bug-MooseX-Role-Parameterized [...] rt.cpan.org" <bug-MooseX-Role-Parameterized [...] rt.cpan.org> |
From: | Istvan Almasi <Istvan.Almasi [...] Yardi.Com> |
Hi,
I've found a really annoying bug while upgrading our existing codebase from v1.02 to v1.10. It could be related to this<https://github.com/moose/MooseX-Role-Parameterized/commit/7f8b5dd8b4086becca2e5885b687b50e792f618a> issue.
Short description: I have two separate classes that use some MXRP roles. The first one has a parameter (call it "class") which is the name of the second class (Str). In the role {} block of the first role I use Class::Load::load_class to load the second class in order to initialize some objects later on.
The problem is that starting with v1.03 the code breaks (I've tested v1.02, v1.03 and v1.10) with this error: Can't locate object method "add_parameter" via package "Moose::Meta::Role" at lib/MooseX/Role/Parameterized.pm line 47. I've found that the problem occurs only if the Class::Load::load_class call is inside the role {} block. I've fixed this bug by moving the load_class call outside the role {} block (added a trigger on the class parameter) but I think this is not a normal behavior to break this way.
I will attach a simplified version of my code which reproduces my case.
Note: the files from the attachment should be in separate files to make sure the second class (called ConcreteNestedClass) is loaded in run-time.
The whole test case in a single file (this will run fine because the ConcreteNestedClass is already loaded when the load_class call occurs):
use strict;
use warnings;
package NestedRole {
use MooseX::Role::Parameterized;
parameter some_param => (
is => 'ro',
isa => 'Str',
default => 'some value'
);
role {
my $param = shift;
has some_words => (
is => 'ro',
isa => 'Str',
default => 'Hello'
);
method yell => sub {
my $self = shift;
print $self->some_words . " ". $param->some_param . "\n";
}
}
};
package ConcreteNestedClass {
use Moose;
with('NestedRole' => { some_param => 'from ConcreteNestedClass' });
}
package Role {
use MooseX::Role::Parameterized;
use Class::Load qw(load_class);
parameter class => (
is => 'ro',
isa => 'Str',
required => 1
);
role {
my $params = shift;
load_class( $params->class );
has some_attr => (
is => 'ro',
isa => 'Str',
default => 'Hello'
);
method say_something => sub {
my $nested_object = initialize_concrete_nested_object($params->class, { some_words => 'Greetings' });
$nested_object->yell();
}
};
sub initialize_concrete_nested_object {
my ($package, $input) = @_;
return $package->new($input);
}
}
package ConcreteClass {
use Moose;
with('Role' => { class => 'ConcreteNestedClass' });
}
package main {
my $concrete_object = ConcreteClass->new();
$concrete_object->say_something();
}
Thanks,
Istvan Almasi
Message body not shown because it is not plain text.