Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

search for similiar text in Moose Attributes

by demonking (Novice)
on May 31, 2013 at 12:55 UTC ( [id://1036240]=perlquestion: print w/replies, xml ) Need Help??

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

Hello,

i wanted to ask, what is the best way to search for some text in Moose Objects?!

package Note; use strict; use warnings; use Moose; use MooseX::Storage; with Storage('format' => 'JSON', 'io' => 'File'); has 'title' => (is => 'rw', isa =>'Str'); has 'message' =>(is=> 'rw', isa =>'Str'); has 'author' =>(is => 'rw', isa =>'Str'); no Moose 1;

How should i search in the elements?! Let's explain it a bit. When a user want to search for a word, then i want to know, if it is in the title,message or author variable.

Should I create a function which returns the hash and iterate through it?

Or is there a better solution?

Replies are listed 'Best First'.
Re: search for similiar text in Moose Attributes
by stephen (Priest) on May 31, 2013 at 19:22 UTC

    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') ];
    ...returns...
    $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!

    stephen

      ++ is insufficient. Bravo!

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
      Thx for the answer :) I like the harder way, it's more flexible. I haven't thought about such a solution.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-04-19 22:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found