How can I build multiple attributes with a single builder in Moose?

只谈情不闲聊 提交于 2019-11-30 14:13:16

What I do in this case, when I don't want to have a separate object as in Ether's answer, is have a lazily built attribute for the intermediate state. So, for example:

has raw_row => (is => 'ro', init_arg => undef, lazy => 1, builder => '_build_raw_row');
has birthdate => (is => 'ro', lazy => 1, builder => '_build_birthdate');

sub _build_raw_row {
   $dbh->selectrow_hashref(...);
}

sub _build_birthdate {
    my $self = shift;
    return $self->raw_row->{birthdate};
}

Repeat the same pattern as birthdate for name, etc.

Reading any of the individual attributes will try to get data from raw_row, whose lazy builder will only run the SQL once. Since your attributes are all readonly, you don't have to worry about updating any object state if one of them changes.

This pattern is useful for things like XML documents, too -- the intermediate state you save can be e.g. a DOM, with individual attributes being lazily built from XPath expressions or what-have-you.

No, an attribute builder can only return one value at a time. You could build both by having each builder set the value of the other attribute before returning, but that gets ugly pretty quickly...

However, if you generally have two pieces of data that go together in some way (e.g. coming from the same DB query as in your case), you can store these values together in one attribute as an object:

has birth_info => (
    is => 'ro', isa => 'MyApp::Data::BirthInfo',
    lazy => 1,
    default => sub {
         MyApp::Data::BirthInfo->new(shift->some_id)
    },
    handles => [ qw(birthdate name) ],
);

package MyApp::Data::BirthInfo;
use Moose;
has some_id => (
    is => 'ro', isa => 'Int',
    trigger => sub {
        # perhaps this object self-populates from the DB when you assign its id?
        # or use some other mechanism to load the row in an ORMish way (perhaps BUILD)
    }
);
has birthdate => (
    is => 'ro', isa => 'Str',
);
has name => (
    is => 'ro', isa => 'Str',
);
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!