Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Moose: Adding methods to a class via attribute traits

by Nasrudin (Acolyte)
on Jan 16, 2012 at 23:55 UTC ( [id://948231]=perlquestion: print w/replies, xml ) Need Help??

Nasrudin has asked for the wisdom of the Perl Monks concerning the following question:

Greetings. Apologies if this has been asked before or is easily found by searching (I've tried, honest).

I'm using Moose and trying to apply a trait to an attribute which automatically adds a method into the containing class. I've done this successfully but I'm thinking there's a better way here, and I'd appreciate any feedback provided.

Thanks in advance.

#!/usr/local/bin/perl use strict; use warnings; package Me::Trait::M; use Moose::Role; has mything => ( isa => 'Maybe[Bool]', is => 'rw', default => 0 ); no Moose::Role; package Moose::Meta::Attribute::Custom::Trait::M; sub register_implementation { 'Me::Trait::M'; } package Me; use Moose; has myattr_yes => ( isa => 'Str', is => 'ro', traits => [qw/M/], default => 'this_is_yes', mything => 1, ); has myattr_no => ( isa => 'Str', is => 'ro', default => 'this_is_no', ); sub BUILD { my $self = shift; my $meta = $self->meta; my @attr = $meta->get_all_attributes(); foreach my $at (@attr) { if ($at->does('Me::Trait::M')) { my $closure = $at->name; my $coderef = sub { my $self = shift; print $self->$closure()."\n"; }; $meta->add_method( 'print_' . $closure => $coderef); } } } no Moose; package main; my $f = Me->new(); $f->print_myattr_yes();

UPDATE: Perusing the way that the deprecated MooseX::AttributeHelpers worked led me to understand Tobyink's comment below. Here is a cleaner solution, involving just the role:

package Me::Trait::M; use Moose::Role; has mything => ( isa => 'Maybe[Bool]', is => 'rw', default => 0 ); after 'install_accessors' => sub { my $self = shift; my $realclass = $self->associated_class(); my $closure = $self->name; my $coderef = sub { my $self = shift; print $self->$closure()."\n"; }; $realclass->add_method( 'print_' . $closure => $coderef ); }; no Moose::Role;

Thanks again for the insight!

UPDATE2: Made the idea a bit clearer, no need to loop the attributes since $self is apparently an attribute class

Replies are listed 'Best First'.
Re: Moose: Adding methods to a class via attribute traits
by tobyink (Canon) on Jan 17, 2012 at 14:19 UTC

    Let's assume that the way Moose::Meta::Attribute::Native does it is the best possible way (given that it's part of Moose core now). Then the best possible way is, rather than including a BUILD method, use:

    after 'install_accessors' => sub { my $self = shift; # ... };

      The idea to look there didn't occur to me, so I looked in that source. Sadly I did not find any reference to using a method modifier on 'install_accessors' (which is really a method in Moose::Meta::Atribute).

      When I blindly replace my BUILD definition with your method modifier idea, I get:

      The method 'install_accessors' was not found in the inheritance hierar +chy for Me at /usr/local/lib/perl5/site_perl/5.10.1/mach/Class/MOP/Cl +ass.pm line 659 Class::MOP::Class::__ANON__('Moose::Meta::Class=HASH(0x8025684c8)' +, 'install_accessors') called at /usr/local/lib/perl5/site_perl/5.10. +1/mach/Class/MOP/Class.pm line 694 Class::MOP::Class::add_after_method_modifier('Moose::Meta::Class=H +ASH(0x8025684c8)', 'install_accessors', 'CODE(0x802568d98)') called a +t /usr/local/lib/perl5/site_perl/5.10.1/mach/Moose/Util.pm line 229 Moose::Util::add_method_modifier('Moose::Meta::Class=HASH(0x802568 +4c8)', 'after', 'ARRAY(0x802443288)') called at /usr/local/lib/perl5/ +site_perl/5.10.1/mach/Moose.pm line 77 Moose::after(undef, 'install_accessors') called at /usr/local/lib/ +perl5/site_perl/5.10.1/mach/Moose/Exporter.pm line 293 Moose::after('install_accessors', 'CODE(0x802568d98)') called at . +/testm line 41

      This makes some sense because my class uses Moose, doesnt use an 'extends' keyword, and isn't necessarily a subclass of Moose::Meta::Attribute. Obviously I'm missing something here, but what?

        Replying to myself here because I was able to use your clue to find out not only what you appear to have meant but a solution. I'll update the main text above in a moment.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://948231]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (7)
As of 2024-04-25 11:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found