Reputation: 439
I have a module which use a number of (stand-alone) modules, and all those modules have the same attribute (a handle to a localization object). Instead of adding that attribute to all classes, I moved that attribute to a Role, which is then consumed by all top-level classes.
Unfortunately now I get the fatal error "Attempt to reload 'Role' aborted" + "Compilation failed in require at Module/Runtime line 317".
I have double and triple checked that I don't consume the Role more than once in all classes, but am a bit stumped on how to attack the problem and find the error. As this fails very early (in/before BEGIN), there is now way (known to me) to debug it either.
The Moo class hierarchy and consumes looks basically like this (it's way to much code to post everything, and it's still too much):
Main class:
SwitchInfo.pm: use Foo::SwitchInfo::DeviceIdent;
SwitchInfo.pm: use Foo::SwitchInfo::Factory;
SwitchInfo.pm: use Foo::SwitchInfo::L10N;
SwitchInfo.pm: use Moo;
The Role:
SwitchInfo/Role/L10N.pm: use Moo::Role;
First level of stand-a-lone classes:
SwitchInfo/L10N: use base 'Locale::Maketext';
SwitchInfo/StackTable.pm: use Moo;
SwitchInfo/StackTable.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/DeviceIdent.pm: use Moo;
SwitchInfo/DeviceIdent.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/NameTable.pm: use Moo;
SwitchInfo/NameTable.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/Factory.pm: use Moo;
SwitchInfo/Factory.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/AliasTable.pm: use Moo;
SwitchInfo/AliasTable.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/Domain.pm: use Moo;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::AliasTable;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::Domain;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::NameTable;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::StackTable;
SwitchInfo/Driver.pm: use Moo;
SwitchInfo/Driver.pm: with 'Foo::SwitchInfo::Role::L10N';
Sub-classes to second level of classes:
SwitchInfo/Driver/Cisco.pm: use Moo;
SwitchInfo/Driver/Cisco.pm: extends 'Foo::SwitchInfo::Driver';
SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Domain;
SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Driver::Extreme::NameTable;
SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Driver::Extreme::StackTable;
SwitchInfo/Driver/Extreme.pm: use Moo;
SwitchInfo/Driver/Extreme.pm: extends 'Foo::SwitchInfo::Driver';
SwitchInfo/Driver/Extreme/StackTable.pm: use Moo;
SwitchInfo/Driver/Extreme/StackTable.pm: extends 'Foo::SwitchInfo::StackTable';
SwitchInfo/Driver/Extreme/NameTable.pm: use Moo;
SwitchInfo/Driver/Extreme/NameTable.pm: extends 'Foo::SwitchInfo::NameTable';
When trying to use the main class I get the following error:
$ cat sw.pl
use strict;
use warnings;
use lib './lib';
use Foo::SwitchInfo;
$
$ perl sw.pl
Attempt to reload Foo/SwitchInfo/Role/L10N.pm aborted.
Compilation failed in require at /opt/perl5/lib/perl5/Module/Runtime.pm line 317.
Compilation failed in require at lib/Foo/SwitchInfo.pm line 3.
BEGIN failed--compilation aborted at lib/Foo/SwitchInfo.pm line 3.
Compilation failed in require at sw.pl line 5.
BEGIN failed--compilation aborted at sw.pl line 5.
$
The head of Foo/SwitchInfo.pm is (with line numbers):
1 package Foo::SwitchInfo;
2
3 use Foo::SwitchInfo::DeviceIdent;
4 use Foo::SwitchInfo::Factory;
5 use Foo::SwitchInfo::L10N;
6 use Types::Standard qw/ ArrayRef InstanceOf Str /;
7 use Type::Utils qw/ as coerce declare from via /;
8
9 use Foo::SNMP;
10
11 use Moo;
12 use namespace::clean;
And the complete Role is like this:
package Foo::SwitchInfo::Role::L10N;
use Types::Standard qw/ InstanceOf /;
use Moo::Role;
has l10n => (
is => 'ro',
isa => InstanceOf['Foo::SwitchInfo::L10N'],
handles => qw/ maketext /,
required => 1,
);
1;
A small test script have verified it's no problem to consume a Role in several classes, and then use those classes in another class.
If there is anyone still reading this long post, do you spot any problems? Or is this use of a Role the supposed use for it? This is my first (real) attempt of using a Role, so I might have got out of bounds here.
Upvotes: 1
Views: 1945
Reputation: 439
Found the error. It turns out that I had a typo in the 'handles' directive in the Role.
was
handles => qw/ maketext /,
should have been
handles => [ qw/ maketext / ],
Figured that out by running
perl -c lib/Foo/SwitchInfo/Role/L10N.pm
which complained loudly
Can't locate maketext.pm in @INC
Upvotes: 2