Search code examples
perlmoose

How can I get a better error message if a required attribute is not supplied in Moose?


I'm brand new to Moose. Up until today our environments have been on Perl 5.8.2 which would not support Moose.

I'm working through some examples, and I thought that the "required => 1" setting on an attribute would be handy, however when I try using that option, the error message that is returned is not really usable.

Here's an example:

cat.pl:

#!/usr/bin/perl

{
    package Cat;
    use Moose;
    use Modern::Perl;

    has 'name' => (
        is => 'ro',
        required => 1,
    );
    sub meow {
        my $self = shift;
        say 'Meow!';
    }
}

use Modern::Perl;

my $alarm = Cat->new();
$alarm->meow();
$alarm->meow();
$alarm->meow();

When I run it:

Attribute (name) is required at /app/perl5/perl-5.10.1/lib/site_perl/5.10.1/aix-thread-multi-64all/Class/MOP/Class.pm line 581
        Class::MOP::Class::_construct_instance('Moose::Meta::Class=HASH(0x110ac1a00)', 'HASH(0x110c3b3c0)') called at /app/perl5/perl-5.10.1/lib/site_perl/5.10.1/aix-thread-multi-64all/Class/MOP/Class.pm line 554
        Class::MOP::Class::new_object('Moose::Meta::Class=HASH(0x110ac1a00)', 'HASH(0x110c3b3c0)') called at /app/perl5/perl-5.10.1/lib/site_perl/5.10.1/aix-thread-multi-64all/Moose/Meta/Class.pm line 258
        Moose::Meta::Class::new_object('Moose::Meta::Class=HASH(0x110ac1a00)', 'HASH(0x110c3b3c0)') called at /app/perl5/perl-5.10.1/lib/site_perl/5.10.1/aix-thread-multi-64all/Moose/Object.pm line 28
        Moose::Object::new('Cat') called at cat.pl line 20

If one of our non-perl operators see an error message like that, they will probably freak out. I'm afraid they will not realize that all 5 lines in the error message are actually a part of the same error.

Is there a way to get a nice error message if a required attribute is not supplied?

Something like croak, I can imagine a message like this:

Attribute (name) is required at cat.pl line 20

Again, I'm new to Moose so this may be an easy setting that I am missing.

Thanks in advance!


Solution

  • I think I may have found a solution to my requirement, but I'm not sure if it is the best solution.

    And, as @Tanktalus points out, there is value to having a detailed error message.

    For the purposes of my question, the MooseX::Constructor::AllErrors extension seems to work:

    #!/usr/bin/perl
    
    {
        package Cat;
        use Moose;
        use MooseX::Constructor::AllErrors;
        use Modern::Perl;
    
        has 'name' => (
            is => 'ro',
            required => 1,
        );
        sub meow {
            my $self = shift;
            say 'Meow!';
        } 
    }
    
    use Modern::Perl;
    
    my $alarm = Cat->new(); 
    $alarm->meow(); 
    $alarm->meow(); 
    $alarm->meow();
    

    On running, I get:

    Attribute (name) is required at cat.pl line 21
    

    Which is what I was thinking.

    Since I am not familiar at all with Moose, is this extension okay to use, or will it "muffle" all of the error messages?