Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Re: search for similiar text in Moose Attributes

by stephen (Priest)
on May 31, 2013 at 19:22 UTC ( #1036299=note: print w/replies, xml ) Need Help??

in reply to search for similiar text in Moose Attributes

An Easy Way

There are a few simple ways of doing it. You could just have a method that calls the attributes that you want to search, something like this:

sub search_me { my $self = shift; my ($search) = @_; my @results = (); foreach my $attr ( qw/title message author/ ) { if ( $self->$attr() =~ m/$search/ ) { push(@results, { 'name' => $attr, 'value' => $self->$attr() } +); } } return @results; }

Which would return something like:

$VAR1 = [ { 'name' => 'title', 'value' => 'My title xyzzy' } ];

But that's no fun! You'd have to change that method every time you changed your Note class. Plus, this is an excellent chance to do something amusing with Moose attributes! What if you could just mark an attribute as searchable, then have a method that goes through and searches those attributes?

A Harder Way

Well, you could define a 'Searchable' trait, like so:

package Note::Attribute::Trait::Searchable { use Moose::Role; Moose::Util::meta_attribute_alias('Searchable'); }

Then have a role that uses that trait to search through your attributes, like so:

package Note::Searchable { use Moose::Role; sub search { my $self = shift; my ($search_string) = @_; my $meta = $self->meta; my @results; # Go through all attributes on your object foreach my $attribute ( map { $meta->get_attribute($_) } sort $meta->get_attribute_list ) { # Skip attributes unless they're specifically searchable unless ( $attribute->does('Note::Attribute::Trait::Searcha +ble') ) { next; } my $reader = $attribute->get_read_method(); my $value = $self->$reader; if ( $value =~ m/$search_string/ ) { push( @results, { 'name' => $attribute->name, 'value' => $value } +); } } return @results; } }

Then finally, in your class, you mark the traits you want as searchable:

package Note { use Moose; with 'Note::Searchable'; # We want to search title, message, and author has 'title' => ( is => 'rw', isa => 'Str', traits => [qw/Searcha +ble/] ); has 'message' => ( is => 'rw', isa => 'Str', traits => [qw/Searcha +ble/] ); has 'author' => ( is => 'rw', isa => 'Str', traits => [qw/Searcha +ble/] ); # We don't want to search "other" has 'other' => ( is => 'rw', isa => 'Str' ); no Moose; }

Then this code returns the same result:

my $note = Note->new( title => 'My title xyzzy', message => 'My message', author => 'me' ); use Data::Dumper; say Dumper [ $note->search('xyzzy') ];
$VAR1 = [ { 'name' => 'title', 'value' => 'My title xyzzy' } ];

There's a lot more up-front work, and it's probably overkill for what you want to do. Still, now you can add and delete new attributes as you please, and they'll be searched properly so long as they're marked searchable!


Replies are listed 'Best First'.
Re^2: search for similiar text in Moose Attributes
by tobyink (Canon) on May 31, 2013 at 21:07 UTC

    ++ is insufficient. Bravo!

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re^2: search for similiar text in Moose Attributes
by demonking (Novice) on Jun 02, 2013 at 10:31 UTC
    Thx for the answer :) I like the harder way, it's more flexible. I haven't thought about such a solution.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1036299]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2020-06-02 18:34 GMT
Find Nodes?
    Voting Booth?
    Do you really want to know if there is extraterrestrial life?

    Results (19 votes). Check out past polls.