Search code examples
perlattributesmoose

Modify Moose attribute methods


I'm creating a list of attributes (more than the three shown below), all of which share common methods. Is it possible to then add a trigger to one of the methods:

# Create a bunch of attributes
for my $attr ( qw( title name address ) ) {
    has $attr => ( is => 'rw', isa => 'Str' );

    around $attr => sub {
        # more stuff here.
    }
}

# Add a trigger
has_another_method 'title' => ( trigger => \&_trigger_title );

I know I can get meta information about attributes, but I haven't found anything that would enable me to change the attribute methods (and perhaps for good reason). Being able to do this would help keep my code clean, and mean that the common bits are all defined in one place. If not, I can just create the attribute separately, and include the trigger method.

Update

The answers have made it clear that changing the attribute after it has been created is not a good idea. Instead, I've opted for a different method which allows me to keep all the attribute options in one place. This example is a little simplistic, but it demonstrates the idea:

# Create a bunch of attributes
for my $attr ( qw( title name address ) ) {

    my %options = ( is => 'rw', isa => 'Str' );

    # Add a trigger to the title attribute.
    $options{ 'trigger' } = \&_trigger_title
        if $attr eq 'title';

    has $attr => ( %options );

    around $attr => sub {
        # more stuff here.
    }
}

Solution

  • Triggers are just an attribute on the attribute, but they are defined to be read only. You could find_meta( $attribute )->get_attribute('trigger')->set_value( $attribute, sub { new trigger }), but you're really breaking encapsulation here.

    I would just declare all common attributes in my for loop, and then declare the special cases elsewhere.