I'm writing a script to help me get proficient in Moose. I've got the following bit of code:
package Dir;
use Moose;
use Modern::Perl;
use File;
has 'dirs' => (is => 'ro', isa => 'HashRef[Dir]' );
has 'files' => (is => 'ro', isa => 'HashRef[File]');
has 'dir_class' => (is => 'ro', isa => 'ClassName', default => 'Dir');
has 'file_class' => (is => 'ro', isa => 'ClassName', default => 'File');
sub BUILD {
my $self = shift;
my $path = $self->path;
my $name = $self->name;
my (%dirs, %files);
# populate dirs attribute with LaborData::Data::Dir objects
opendir my $dh, $path or die "Can't opendir '$path': $!";
# Get files and dirs and separate them out
my @dirs_and_files = grep { ! m{^\.$|^\.\.$} } readdir $dh;
closedir $dh or die "Can't closedir '$path': $!";
my @dir_names = grep { -d "$path/$_" } grep { !m{^\.} } @dirs_and_files;
my @file_names = grep { -f "$path/$_" } grep { !m{^\.} } @dirs_and_files;
# Create objects
map { $dirs{$_} = $self->dir_class->new ( path => $path . '/' . $_ ) } @dir_names;
map { $files{$_} = $self->file_class->new ( path => $path . '/' . $_ ) } @file_names;
# Set attributes
$self->dirs ( \%dirs );
$self->files ( \%files );
}
The code results in the following error: died: Moose::Exception::CannotAssignValueToReadOnlyAccessor (Cannot assign a value to a read-only accessor at reader Dir::dirs
To get around this error, I could either make the attributes rw
or use builder
methods for the dirs
and files
attributes. The former solution is undesirable and the latter solution will require duplication of code (for example, the directory will need to be opened twice) and so is also undesirable.
What is the best solution to this problem?