Using Moo

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.