This is a little story of a little bug. This gremlin suddenly appeared in a CGI.PM web-based application I work with. To make a long story short, an email was coming out something like this . . .
389939
Subject:Update to Report #389939 by B. bloggins Description:389939 #389939: TPDD Now Deploying to monitoring for the MySQL servers.
. . . when it should have been some thing like this:
Subject: TPDD Update to Report #389939 by B. bloggins
TPDD Now Deploying to monitoring for the MySQL servers.
After about an hour tracking things back, my team and I narrowed it down to this line of code:
$self->send_TXT_email(CGI::param("rep_no"),$rep_object, $subject,$user_ref);
We scratched our respective heads on this for a while, because for user type ‘A’, it worked fine; but for user type ‘B’, it did not. And they were both using the same web page to send the email.
But before we went and reinstalled our mail server, I remembered that this is how CGI::param is intended to work:
@values = $query->param('foo'); # or $value = $query->param('foo');
Arghhh! A wretched, two-faced overloaded method! So, depending on how you call the method, the returned results may differ.
Looking deeper, I discovered that the page was in fact receiving three values for CGT::param(“rep_no”) when user was of type ‘B’, and thus sending that as an array to the send_TXT_email
method, and as a result, buggering up the email content.
Even more digging I found out the root cause was a web page that was three pages back from the one that was sending the email. Seems some-one made a change to fix one bug and as a result caused this one.
This quick fix for this (as we could not change the root page) was
my $rep_no=CGT::param("rep_no"); $self->send_TXT_email($rep_no,$rep_object,$subject,$user_ref);
Lesson learned: never trust a wretched, two-faced overloaded method.
3 Comments. Leave new
Perl – a million solutions for every problem.
Would this also do it?
$self->send_TXT_email(scalar($rep_no=CGT::param(“rep_no”)),$rep_object,$subject,$user_ref);
$self->send_TXT_email(scalar($rep_no=CGT::param(”rep_no”)),$rep_object,$subject,$user_ref);
Actually, the scalar( $x = param() ) is overkill. Assigning ‘param()’ to a scalar already forces a scalar context. So
$self->send_TXT_email(scalar(CGI::param(”rep_no”)),$rep_object,$subject,$user_ref);
or
$self->send_TXT_email(($rep_no=CGI::param(”rep_no”)),$rep_object,$subject,$user_ref);
or even
$self->send_TXT_email(''.CGI::param(”rep_no”),$rep_object,$subject,$user_ref);
would work just fine. Although splitting it in two statements, like John did, is a more readable way of doing it.
I could be wrong here, but you could also embrace the overloading:
($value) = $query->param(‘foo’);
You’ll get the param output as an array, where it will put the first value in the list into $value.