Search code examples
perlmoo

How to NOT execute trigger while constructing object


I have this code:

package Foo;
use Moo;

has attr => ( is => "rw", trigger => 1 );

sub _trigger_attr 
    { print "trigger! value:". shift->attr ."\n" }


package main;
use Foo;

my $foo = Foo->new( attr => 1 );
$foo->attr( 2 );

It returns:

$ perl test.pl
trigger! value:1
trigger! value:2

This is default, documented behavior of Triggers in Moo.

How can I disable trigger execution if the attribute is set via constructor?

Of course I can do it like this:

package Foo;
use Moo;

has attr        => ( is => "rw", trigger => 1 );
has useTriggers => ( is => "rw", default => 0 );

sub _trigger_attr 
{ 
    my $self = shift;
    print "trigger! value:". $self->attr ."\n" if $self->useTriggers 
}

package main;
use Foo;

my $foo = Foo->new( attr => 1 );
$foo->useTriggers( 1 );
$foo->attr( 2 );

And get:

$ perl testt.pl
trigger! value:2

So it works, but ... it feels wrong ;).


Solution

  • I don't know much about Moo, but in Moose you can implement your own code after the constructor. If you can do something like this in Moo it would give you the desired effect.

    sub BUILD {
        my $self = shift;
    
        # Sets "useTriggers" AFTER the object is already constructed.
        $self->useTriggers(1);
    };
    

    This would cause useTriggers to be set just after construction so the trigger would be active after the object is constructed, but not before it is constructed.

    So you should be able to write:

    my $foo->new(attr => 1);
    $foo->attr(2);
    

    And get the same output.