-2

Here is the current method:

sub new {
    my ($package, $message) = (shift, shift);
    my %params = @_;
    return bless { message => $message, %params }, $package;
}

This method returns basically an error string , but I want to modify it so it will also be able to take my new error structure and return the string from the error hash. I can't get my head around how to use bless. The %params accepts runtime parameter but they can be ignored for now I would think.

Here is the error structure:

 # this constant is an example of an error library (just included 1 error for example)
    use constant {

        CABLING_ERROR => {
        errorCode => 561,
        message => "Cabling incorrect to device in server A4r, contact DCT ",
        tt => { template => 'cable'},
        fatal => 1,
        link =>'http://www.error-fix.com/cabling
        },
};

I just started throwing down some code to start , it's a poor attempt but this is how I began modifying the new() method:

sub new {
    my ($package, $message) = (shift, shift);
    # defining new error hash
    my $hash($errorCode, $message, $tt, $fatal, $link) = (shift, shift, shift, shift);
    my %params = @_;

    if(exists $hash->{errorCode}) {
    return bless { errorCode => $errorCode, message => $message, tt => $tt, fatal => $fatal, link => $link}, %params;
}   
    else {
        return bless { message => $message, %params }, $package;
}
}

My understanding of bless is that it makes object of hash refs. The errors are held in the constant list. Here is an example of how it is to be executed:

if(!device_model) {
    die  ARC::Builder::Error->new(CABLING_ERROR);

}

UPDATE: I have been trying to unit test your solution @simbabque but I keep getting an empty string as a return value instead of the error message string. Maybe it's my test that it isn't set up correctly? Below is an example of the test I created:

my $error = CABLING_ERROR;

my $exp_out_A = ($error->{message});

my $error_in = new($error);

diag($error_in);

is($error_in, $exp_out_A, 'Correct message output');
Paul Russell
  • 179
  • 10
  • Why do you have a constant? Please [edit] your question and add an example call for the constructor with input and output. - Actually, do you know at all what the `bless` does? It doesn't sound like that. Please try to also explain a bit more what this is supposed to do, and in what context. I smell an X/Y problem. ;) – simbabque Mar 23 '16 at 18:58
  • @simbabque makes good points. I am just going to point out that *if* you need to define a constant hash, you should use a module such as `Const::Fast`. The fields of `CABLING_ERROR` defined above are modifiable. Also, post code that others can easily run. Your code should ***NOT*** contain any *syntax errors* unless those are the focus of your question. – Sinan Ünür Mar 23 '16 at 19:11
  • You are better off using [Exception::Class](https://metacpan.org/pod/Exception::Class) or [Throwable::Error](https://metacpan.org/pod/Throwable::Error) – Sinan Ünür Mar 23 '16 at 19:14
  • I will take a look at Const::Fast . Apologies , I am very new to perl. The system already has its own Exception module in place. I am only dealing with the fatal errors that will cause the system to crash (die). – Paul Russell Mar 23 '16 at 19:20
  • 1
    Besides the syntax error in the last code block (it's supposed to be `Arc::Builder::Error` with two `::`), I think it might be wiser to subclass that thing, and make one subclass per error type. That way you have something that is _constant_ (adjective), but you are avoiding complicated constants. I agree with Sinan about the exception modules though. What `bless` does can best be described as taking a data structure and sticking a label on it. But it does not have to be a hash. The hash is just very typical, because it's flexible. – simbabque Mar 23 '16 at 19:24

1 Answers1

2

What you actually want is your constructor to distinguish between if it was called with a message string, or with a hash of a known form that contains the message string. Basically you want to coerce the message attribute.

sub new {
  my ($package, $thing) = (shift, shift);
  my %params = @_;

  if (ref $thing eq 'HASH') {
    return bless { message => $thing->{message}, %params }, $package;
  }

  return bless { message => $thing, %params }, $package;
}

That's it. Just check the ref of the param you are getting. If it's a hash reference, it will be 'HASH'. If it's a simple string, it will be undef.

In case you want to build up more %params automatically from your hash reference, that would look something like this.

return bless { message => $thing->{message}, foo => $thing->{foo}, %params }, $package;
simbabque
  • 53,749
  • 8
  • 73
  • 136