Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Prepend a Moose attribute when changed

by FryingFinn (Sexton)
on Feb 08, 2019 at 01:36 UTC ( #1229582=perlquestion: print w/replies, xml ) Need Help??
FryingFinn has asked for the wisdom of the Perl Monks concerning the following question:

Hi folk:

I'm fairly new to Moose & I cannot seem to figure out this problem: I have a string attribute to which I wish to prepend another string... I try with builder: no luck; I tried w BUILDARGS which works when an instance is initiated, but not when I try to change the attribute...

My testing module:

package Test; use Moose; my $prepend = '/some_string/'; has 'fname' => (is => 'rw', isa => 'Str'); has 'appended' => ( is => 'rw', isa => 'Str', # lazy => 1, #builder => 'set_appended' ); 1; sub BUILDARGS { my $class = shift; my %args = ref $_[0] ? %{$_[0]} : @_; $args{appended} = $prepend . $args{appended} if exists $args{appe +nded}; return \%args; } sub set_appended { my $self = shift; my $value = $self->appended; return $prepend . $value; }

My test program

use 5.010; use strict; use warnings; use lib "."; use Test; my $t = new Test( fname => "fred", appended => "this_is_appended_string"); say $t->fname; say $t->appended; $t->appended ('another_string'); say $t->appended;

The output

fred /some_string/this_is_appended_string another_string

Thx in advance..

Replies are listed 'Best First'.
Re: Prepend a Moose attribute when changed
by 1nickt (Abbot) on Feb 08, 2019 at 02:45 UTC

    Hi, what you are looking for is a coercion. (I'd also recommend using Type::Tiny for type constraints).

    This can be done in Moose:

    use strict; use warnings; use feature 'say'; package MyClass { use Moose; use Types::Standard 'Str'; has foo => ( is => 'rw', isa => Str->where(sub {/^bar\./})->plus_coercions(Str, sub +{'bar.' . $_}), coerce => 1, ); } my $obj = MyClass->new( foo => 'baz' ); say $obj->foo; # 'bar.baz $obj->foo('qux'); say $obj->foo; # 'bar.qux' __END__
    ... but IMHO it's much simpler (as are most things) in Moo:
    use strict; use warnings; use feature 'say'; package MyClass { use Moo; use Types::Standard 'Str'; has foo => ( is => 'rw', isa => Str, coerce => sub {'bar.' . shift}, ); } my $obj = MyClass->new( foo => 'baz' ); say $obj->foo; # 'bar.baz' $obj->foo('qux'); say $obj->foo; # 'bar.qux' __END__

    Hope this helps!


    The way forward always starts with a minimal test.
Re: Prepend a Moose attribute when changed
by Haarg (Deacon) on Feb 08, 2019 at 13:19 UTC
    It may make more sense to prepend the extra string in your accessor.
    package Test; use Moose; my $prepend = '/some_string/'; has appended => (is => 'rw'); around appended => sub { my ($orig, $self) = (shift, shift); my $value = $self->$orig(@_); return $prepend . $value; }; 1;
Re: Prepend a Moose attribute when changed
by tobyink (Abbot) on Feb 08, 2019 at 14:45 UTC

    This seems the easiest way to me…

    use 5.010; use strict; use warnings; { package Test; use Moose; my $prepend = '/some_string/'; has _appended => (is => 'rw', init_arg => 'appended'); sub appended { $prepend . shift->_appended(@_) } } my $t = Test->new(appended => "this_is_appended_string"); say $t->appended; $t->appended('another_string'); say $t->appended;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1229582]
Approved by Athanasius
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (9)
As of 2019-02-22 20:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    I use postfix dereferencing ...









    Results (119 votes). Check out past polls.

    Notices?