Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Checking for Presence of Optional Attribute in Moose Object

by roho (Monsignor)
on Jul 03, 2010 at 21:28 UTC ( #847938=perlquestion: print w/ replies, xml ) Need Help??
roho has asked for the wisdom of the Perl Monks concerning the following question:

I have a Moose class with an attribute that is not required. When I try to access this attribute in an object where it is not present, the warning message "Use of uninitialized value in concatenation (.) or string" is generated. How can I check for the presence of an optional attribute without generating the warning message?

The sample code below is a simple Moose class with 1 required attribute (name) and 1 optional attribute (age). The 'show_person' method generates the warning message because $self->age() is not present in the current object.

Just referencing $self->age() in 'show_person' to test it generates the warning, as in:
if ($self->age() ne '') {...};

#!/usr/bin/perl package Person; use Moose; has 'name' => ( is => 'ro', isa => 'Str', required => 1); has 'age' => ( is => 'ro', isa => 'Str'); sub show_person { my $self = shift; return $self->name() . " " . $self->age(); } __PACKAGE__->meta->make_immutable; no Moose; 1; my $person = Person->new(name => "Bob"); print "\n", $person->show_person(), "\n";

"Its not how hard you work, its how much you get done."

Comment on Checking for Presence of Optional Attribute in Moose Object
Select or Download Code
Re: Checking for Presence of Optional Attribute in Moose Object
by Khen1950fx (Canon) on Jul 04, 2010 at 04:23 UTC
    I'm not an expert in Moose, but looking at it makes me wonder why you are referencing it. I took the reference to age out of the sub.
    sub show_person { my $self = shift; return $self->name(); }
    If it's not required, then it wasn't necessary to return it, at least to my way of thinking. My logic could be off, which happens frequently, but here's the code that I ran. It returns "Bob" with no warnings.
    package Person; use Moose; has 'name' => ( is => 'ro', isa => 'Str', required => 1); has 'age' => ( is => 'ro', isa => 'Str'); sub show_person { my $self = shift; return $self->name(); } __PACKAGE__->meta->make_immutable; no Moose; 1; my $person = Person->new(name => "Bob"); print $person->show_person(), "\n";
      The sample code is only meant to describe the problem. I want to be able to add the optional attribute value to a display line if the attribute is present. The predicate suggestion by FalseVinylShrub and Your Mother solved the problem. Many thanks.

      "Its not how hard you work, its how much you get done."

Re: Checking for Presence of Optional Attribute in Moose Object
by FalseVinylShrub (Chaplain) on Jul 04, 2010 at 04:41 UTC

    Hi

    I think your test should work without the warning if you use if (defined $self->age) { ... }.

    According to Moose::Manual::Attributes, you could also set up a predicate for that attribute:

    has 'age' => ( is => 'ro', isa => 'Str', predicate => 'has_age' ); if ($self->has_age) { ... }

    The predicate allows you to have undefined or false values and still know whether it's ever been set or not.

    On the other hand, if you just want to be able to interpolate an empty value into a string without warnings, how about putting a default of '':

    has 'age' => ( is => 'ro', isa => 'Str', default => '', );

    Assumes that '' is not a valid age... But that sounds like a reasonable assumption.

    FalseVinylShrub

    Disclaimer: Please review and test code, and use at your own risk... If I answer a question, I would like to hear if and how you solved your problem.

Re: Checking for Presence of Optional Attribute in Moose Object
by Your Mother (Canon) on Jul 04, 2010 at 04:47 UTC

    A way to do it is with a predicate.

    BEGIN { package Person; use Moose; use overload '""' => sub { +shift->show_person }, fallback => 1; has 'name' => is => 'ro', isa => 'Str', required => 1; has 'age' => is => 'ro', isa => 'Str', predicate => 'has_age'; sub show_person { my $self = shift; join(", ", $self->name, $self->has_age ? $self->age : "age unknown"); } __PACKAGE__->meta->make_immutable; no Moose; 1; } my $person = Person->new({ name => "Bob" }); print $person->show_person, "\n"; print Person->new({ name => "Your Uncle", age => 93 }), "\n";

    More here: Moose::Manual::Attributes.

    (Update: man! I waited for hours to see if anyone would bite on this and when I finally go to post, FalseVinylShrub hit create while I was typing.)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://847938]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2014-12-27 16:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (177 votes), past polls