Re: Moose Question

[email protected] (Stevan Little)
Newsgroups perl.moose
Message-ID <[email protected]>
Chris,

On Mar 19, 2008, at 5:22 PM, Christopher Brown wrote:
> I do have follow-up questions, though.  Suppose I want to generate  
> those
> plain old methods dynamically.  Is there a simple, moose way to do  
> this in
> the BUILD subroutine.   On e way to accomplish this is to assign an
> anonymous subroutine to a glob.  Like this:

The BUILD method runs every time an object is created (per-instance)  
and by altering the symbol table you are adding a method to the class  
itself. If the method you add is a closure around a $row (which it  
seems that is what you are going for) you will only be able to use  
one instance of this class at a time, otherwise the method you add  
will override one another.

> package My::App;
>
> use Moose;
> has name => ( is => 'rw', isa=>'Str' );
>
> sub BUILD {
>         **__PACKAGE__::method = sub { print "hello world\n"; } ;*
> }
>
> package main;
> my $app = My::App->new( { name => 'Moose' } );
> $app->method;
>
>
> But I don't want to do that.  I want to do it the Moose way.

As I said above, this is not really a good idea, but the Moosey way  
to do it would be:

sub BUILD {
     my $self = shift;
     $self->meta->add_method('method' => sub { ... });
}

This is documented in Class::MOP::Class.

> I can hear you ask, but why would you want to do that?  Well  
> suppose, I
> create an object that wraps a query.  If I can iterate over the  
> record set I
> can replace the data slot with the new record and still named  
> methods that
> act as accessors to the record.  This beats the snot out of trying to
> instanciate a row object for each record.

I think, if I understand what you are trying to do correctly, you  
should do something like this:

(WARNING: this is completely untested code, but it **should** work)

package RecordSetIterator;
use Moose;

has 'record_set' => (
     is  => 'ro',
     isa => 'RecordSet',
);

# list the fields you want to
# fetch from the current record
my @fields = qw[
     first_name
     last_name
];

has 'current_record' => (
     is      => 'ro',
     isa     => 'Record',
     lazy    => 1,
     default => sub {
         my $self = shift;
         $self->record_set->next() # grab the first one
     },
     trigger => sub {
         my $self = shift;
         # whenever this attribute is
         # updated, it will clear all
         # the fields for you.
         $self->$_() for map { '_clear_' . $_ } @fields;
     }
);

# define the attributes
# for all the fields.
has $_ => (
     is      => 'ro',
     # make sure they have a clearer ...
     clearer => ('_clear_' . $_)
     lazy    => 1,
     default => sub {
         my $self = shift;
         # fetch the value from
         # the current record
         $self->current_record->$_();
     },
) for @fields;

sub get_next_record {
     my $self = shift;
     $self->current_record($self->record_set->next());
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.