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.
    }
}

Answers


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.


Attribute methods are composed when they are constructed, so it is generally a good practice to have all the options available when you create it with the has directive. However, currently there is nothing special being done with trigger methods, so you could do this, to get around the read-onlyness of the 'trigger' option:

my $attr = __PACKAGE__->meta->get_attribute('title')->meta->get_attribute('trigger')->set_raw_value('_trigger_sub_name');

However this is delving rather excessively into the innards of Moose; if the implementation ever changes, you can be SOL (plus you would be violating constraints that are there for a reason). So it would be much better to set up your triggers as:

has $_ => (
    is => 'rw', isa => 'Str',
    trigger => '_trigger_' . $_,
) for (qw(title name address));

sub _trigger_title {
    # implementation here
}
sub _trigger_name {
    # implementation here
}
sub _trigger_address {
    # implementation here
}

Need Your Help

Does Qt Linguist offer the ability to add new entries to the editable .ts file?

c++ qt translation

I didn't find a way to do this - only to edit the translations to the existing fields.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.