使用Moose,是否可以创建一次构建多个属性的构建器?
我有一个项目,其中对象有几个’集’字段 – 如果请求集合中的任何成员,我想继续并填充所有.我的假设是,如果我需要这个名字,我还需要生日,因为它们在同一个表中,所以在一个查询中获得两者都会更快.
我不确定我的问题是否足够清楚,但希望一些示例代码能够说清楚.
是)我有的:
Package WidgetPerson; use Moose; has id => (is => 'ro',isa => 'Int' ); has name => (is => 'ro',lazy => 1,builder => '_build_name'); has birthdate => (is => 'ro',builder => '_build_birthdate'); has address => (is => 'ro',builder => '_build_address'); sub _build_name { my $self = shift; my ($name) = $dbh->selectrow_array("SELECT name FROM people WHERE id = ?",{},$self->id); return $name; } sub _build_birthdate { my $self = shift; my ($date) = $dbh->selectrow_array("SELECT birthdate FROM people WHERE id = ?",$self->id); return $date; } sub _build_address { my $self = shift; my ($date) = $dbh->selectrow_array("SELECT address FROM addresses WHERE person_id = ?",$self->id); return $date; }
但我想要的是:
has name => (is => 'ro',isa => 'Str',builder => '_build_stuff'); has birthdate => (is => 'ro',isa => 'Date',builder => '_build_stuff'); has address => (is => 'ro',isa => 'Address',builder => '_build_address'); sub _build_stuff { my $self = shift; my ($name,$date) = $dbh->selectrow_array("SELECT name,birthdate FROM people WHERE id = ?",$self->id); $self->name($name); $self->birthdate($date); } sub _build_address { #same as before }
解决方法
在这种情况下,当我不想在Ether的答案中有一个单独的对象时,我所做的是对于中间状态具有延迟构建的属性.所以,例如:
has raw_row => (is => 'ro',init_arg => undef,builder => '_build_raw_row'); has birthdate => (is => 'ro',builder => '_build_birthdate'); sub _build_raw_row { $dbh->selectrow_hashref(...); } sub _build_birthdate { my $self = shift; return $self->raw_row->{birthdate}; }
为姓名等重复与birthdate相同的模式.
读取任何单个属性将尝试从raw_row获取数据,其惰性构建器将仅运行sql一次.由于您的属性都是只读的,因此如果其中一个对象状态发生更改,则无需担心更新任何对象状态.
这种模式对XML文档之类的东西也很有用 – 你保存的中间状态可以是例如一个DOM,其中各个属性是从XPath表达式或者你有什么内容构建的.