Moo simplifies OO in Perl.
Here is a Moo class that will provide some information about a file. I will use D.A Golden’s Path::Tiny, because I use this module in almost every script that I write.
package File::Info;
use Moo;
use v5.16;
#-------------------------------------------------------------------------------
# Base class to provide information about a given file.
#-------------------------------------------------------------------------------
use Path::Tiny;
use File::stat;
use Carp;
use namespace::clean; #--- Dont export unintentionally
#-------------------------------------------------------------------------------
# Attributes
#-------------------------------------------------------------------------------
has file => (
is => 'ro',
isa => sub {
Carp::croak(qq{'in_file' needs to be an existing file and a Path::Tiny Object!})
unless (ref $_[0] eq 'Path::Tiny' and $_[0]->exists);
},
coerce => sub {
return $_[0]
if ( ref $_[0] eq 'Path::Tiny' );
return path( $_[0] );
},
required => 1
);
has file_stat => (
is => 'rwp',
isa => sub {
Carp::croak(qq{$_[0] is not a File::stat::stat!})
unless ( $_[0] and ( ref $_[0] ) );
},
);
#-------------------------------------------------------------------------------
# Builders and Triggers
#-------------------------------------------------------------------------------
sub BUILD {
my ($self) = @_;
$self->_set_file_stat( File::stat::stat( $self->file ) )
or Carp::croak( qq{File stat failed to get the file stat for, }
. $self->file
. qq{!: $!} );
}
1;
It would be a good idea to test this module before we proceed further.
I found a this Test::Modern module by Toby Inkster(who always does good stuff). It’s a testing module that includes many other testing modules(Also see Test::Most).
Here’s a test to make sure that all’s ok with my File::Info module.
use Test::Modern; #-- I wonder will it be modern in 10 years time??
use FindBin qw($Bin);
use lib qq{$Bin/../lib}; #-- Where File::Info is located.
use File::Info;
my $fi = object_ok(
sub { File::Info->new( file => qq{IMAG0029.jpg} ) },
'$fi',
isa => [qw(Moo::Object )],
can => [qw( file file_stat )],
clean => 1,
more => sub {
my $file_info_obj = shift;
isa_ok( $file_info_obj->file, 'Path::Tiny',
q{File::Info 'file' is a Path::Tiny object.} );
is( $file_info_obj->file->basename,
qq{IMAG0029.jpg},
q{File::Info 'file' has the correct file basename.} );
isa_ok( $file_info_obj->file_stat, q{File::stat},
qq{File::Info 'file_stat' is a 'File::stat'.} );
like( $file_info_obj->file_stat->size,
qr/^[0-9]+$/,
q{File::Info 'file_stat->size' returns a numeric file size.} );
},
);
done_testing();
I ran this test script and got the following results ( on the first attempt of course :)).
Moo > prove -v t/test_file.t
t/test_file.t ..
# Subtest: $fi ok
ok 1 - instantiate $fi
ok 2 - $fi is blessed
ok 3 - '$fi' isa 'Moo::Object'
ok 4 - File::Info->can(...)
ok 5 - File::Info contains no imported functions
# Subtest: more tests for $fi
ok 1 - 'File::Info 'file' is a Path::Tiny object.' isa 'Path::Tiny'
ok 2 - File::Info 'file' has the correct file basename.
ok 3 - 'File::Info 'file_stat' is a 'File::stat'.' isa 'File::stat'
ok 4 - File::Info 'file_stat->size' returns a numeric file size.
ok 5 - no exception thrown by additional tests
1..5
ok 6 - more tests for $fi
1..6
ok 1 - $fi ok
ok 2 - no (unexpected) warnings (via done_testing)
1..2
ok
All tests successful.
Files=1, Tests=2, 0 wallclock secs ( 0.03 usr 0.01 sys + 0.09 cusr 0.00 csys = 0.13 CPU)
Result: PASS
[21:42 - 0.37]
[austin@the-general-II 64] Moo >
Test::Modern seems pretty cool. My File::Info module seems to be ok so far. Now to add some more useful functionality.