If you have an attribute that needs to be modified any time it is set, is there a slick way of doing this short of writing the accessor yourself and mucking around directly with the content of $self
, as done in this example?
package Foo;
use Moose;
has 'bar' => (
isa => 'Str',
reader => 'get_bar',
);
sub set_bar {
my ($self, $bar) = @_;
$self->{bar} = "modified: $bar";
}
I considered trigger
, but it seemed to require the same approach.
Is working directly with the hash reference in $self
considered bad practice in Moose, or am I worrying about a non-issue?
You can use the method modifier 'around'. Something like this:
has 'bar' => (
isa => 'Str',
reader => 'get_bar',
writer => 'set_bar'
);
around 'set_bar' => sub {
my ($next, $self, $bar) = @_;
$self->$next( "Modified: $bar" );
};
And yes, working directly with the hash values is considered bad practice.
Also, please don't assume that the option I presented is necessarily the right one. Using subtypes and coercion is going to be the right solution most of the time - if you think about your parameter in terms of a type that can possibly be reused throughout your application will lead to much better design that the kind of arbitrary modifications that can be done using 'around'. See answer from @daotoad.
I'm not sure what kind of modification you need, but you might be able to achieve what you need by using type coercion:
package Foo;
use Moose;
use Moose::Util::TypeConstraints;
subtype 'ModStr'
=> as 'Str'
=> where { /^modified: /};
coerce 'ModStr'
=> from 'Str'
=> via { "modified: $_" };
has 'bar' => (
isa => 'ModStr',
is => 'rw',
coerce => 1,
);
If you use this approach, not all values will be modified. Anything that passes validation as a ModStr will be used directly:
my $f = Foo->new();
$f->bar('modified: bar'); # Set without modification
This weakness could be OK or it could make this approach unusable. In the right circumstances, it might even be an advantage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With