Search code examples
perlmoose

How to merge HashRef in Moose attribute writer?


Having a simple example code

use Modern::Perl;
use Data::Dumper;

package My;
use Moose;
use Method::Signatures::Simple;
has 'result' => (
    is => 'rw',
    isa => 'HashRef',
    default => sub{{}},
    clearer => 'clear_result'
);

method run {
    $self->clear_result;                 #clearing the result
    $self->result( $self->run_part1 );
    $self->do_something;
    $self->result( $self->run_part3 );   #need merge
}

method do_something {
    $self->result( $self->run_part2 );   #need merge
}

method run_part1 { return { aaa => 'aaa' } }
method run_part2 { return { bbb => 'bbb' } }
method run_part3 { return { ccc => 'ccc' } }

package main;
my $p = My->new;
say Dumper $p->run;

the result (ofcourse) is:

$VAR1 = {
          'ccc' => 'ccc'
        };

I want the result:

$VAR1 = {
          'aaa' => 'aaa'
          'bbb' => 'bbb'
          'ccc' => 'ccc'
        };

so, the question is - how to merge the $self->result HashRef when setting it?

Yes, i can add new method add_result like:

method add_result($hr) {
    use Hash::Merge::Simple qw(merge);
    $self->result( merge $self->result, $hr );
}

and change everywhere in my code the $self->result to $self->add_result but wonder if there is another solution...


Solution

  • has 'result' => (
        acccessor => '_result',
        isa => 'HashRef',
        default => sub{{}},
        clearer => 'clear_result'
    );
    
    sub result {
        my $self = shift;
        if (@_) {
            my ($hr) = @_;
            return $self->_result( ... merged hash ...);
        } else {
            return $self->_result();
        }   
    }