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.