Perl 用Moo包装Web服务
我最近接管了一个Perl客户机的维护工作,该客户机包装了一个装运web服务。处于初始状态的项目使用直接映射到web服务对象的Moo对象,例如有类Parcel、Address和Label 在API的v2中,您必须将表示其中一个对象的所有数据发布到web服务,然后返回该对象的唯一id,该id必须用于所有后续事务 例如,如果我发布:Perl 用Moo包装Web服务,perl,moo,easypost,Perl,Moo,Easypost,我最近接管了一个Perl客户机的维护工作,该客户机包装了一个装运web服务。处于初始状态的项目使用直接映射到web服务对象的Moo对象,例如有类Parcel、Address和Label 在API的v2中,您必须将表示其中一个对象的所有数据发布到web服务,然后返回该对象的唯一id,该id必须用于所有后续事务 例如,如果我发布: { name => 'Hunter', street => '121 Baker St', city => 'New York',
{ name => 'Hunter',
street => '121 Baker St',
city => 'New York',
state => 'NY',
}
我将返回相同的数据,但包含一个id:
{ id => 'adr_xq1411',
name => 'Hunter',
street => '121 Baker St',
city => 'New York',
state => 'NY',
}
我很难决定如何创建这些对象。目前,我有一个构造函数,它执行实际的发布以获取ID,然后修改当前对象:
sub BUILD {
my $self = shift;
my $requestor = Net::Easypost::Request->new;
my $resp = $requestor->post(
'/addresses',
$self->serialize( [qw(street1 street2 city state zip)] )
);
# save the id for this Address from Easypost
$self->id( $resp->{id} );
return $self;
}
在用Perl包装web服务时,这是一种常见的方法吗?似乎理想的方法是发布到web服务并一次性创建Address对象的所有属性,但在Moo(se)中,一旦使用构建方法,对象已经创建
我对包装web服务的习惯用法不太熟悉,有没有比这更简单的方法
如有任何建议/意见/建议,将不胜感激 这当然是一种方法。将
BUILD
方法分解成一个角色可能是一个好主意。比如:
package MyApp::PostOnBuild;
use Moo::Role;
has id => (is => 'rwp');
has endpoint => (is => 'ro', default => sub { '/addresses' });
has requestor => (is => 'ro', default => sub { Net::Easypost::Request->new });
has field_names => (is => 'ro', builder => 1);
requires '_build_field_names';
requires 'serialize'; # or maybe just implement serialize within this role!
sub BUILD { }
after BUILD => sub {
my $self = shift;
my $resp = $self->requestor->post($self->endpoint, $self->serialize($self->field_names));
$self->_set_id( $resp->{id} );
};
my $adr = MyApp::Address->new(
street1 => '123 Example Lane',
city => 'Sydney',
state => 'NSW',
zip => '2035',
requestor => Test::Requestor->new,
);
现在,类不需要定义自己的BUILD
方法。他们所需要做的就是:
package MyApp::Address;
use Moo;
with 'MyApp::PostOnBuild';
my @fields = qw/ street1 street2 city state zip /;
has $_ => (is => 'ro') for @fields;
sub _build_field_names { \@fields }
sub serialize { ... } # would this method be better defined in MyApp::PostOnBuild??
请注意,requestor
现在是一个属性,因此在测试类时,可以执行以下操作:
package MyApp::PostOnBuild;
use Moo::Role;
has id => (is => 'rwp');
has endpoint => (is => 'ro', default => sub { '/addresses' });
has requestor => (is => 'ro', default => sub { Net::Easypost::Request->new });
has field_names => (is => 'ro', builder => 1);
requires '_build_field_names';
requires 'serialize'; # or maybe just implement serialize within this role!
sub BUILD { }
after BUILD => sub {
my $self = shift;
my $resp = $self->requestor->post($self->endpoint, $self->serialize($self->field_names));
$self->_set_id( $resp->{id} );
};
my $adr = MyApp::Address->new(
street1 => '123 Example Lane',
city => 'Sydney',
state => 'NSW',
zip => '2035',
requestor => Test::Requestor->new,
);
这当然是一种方法。将
BUILD
方法分解成一个角色可能是一个好主意。比如:
package MyApp::PostOnBuild;
use Moo::Role;
has id => (is => 'rwp');
has endpoint => (is => 'ro', default => sub { '/addresses' });
has requestor => (is => 'ro', default => sub { Net::Easypost::Request->new });
has field_names => (is => 'ro', builder => 1);
requires '_build_field_names';
requires 'serialize'; # or maybe just implement serialize within this role!
sub BUILD { }
after BUILD => sub {
my $self = shift;
my $resp = $self->requestor->post($self->endpoint, $self->serialize($self->field_names));
$self->_set_id( $resp->{id} );
};
my $adr = MyApp::Address->new(
street1 => '123 Example Lane',
city => 'Sydney',
state => 'NSW',
zip => '2035',
requestor => Test::Requestor->new,
);
现在,类不需要定义自己的BUILD
方法。他们所需要做的就是:
package MyApp::Address;
use Moo;
with 'MyApp::PostOnBuild';
my @fields = qw/ street1 street2 city state zip /;
has $_ => (is => 'ro') for @fields;
sub _build_field_names { \@fields }
sub serialize { ... } # would this method be better defined in MyApp::PostOnBuild??
请注意,requestor
现在是一个属性,因此在测试类时,可以执行以下操作:
package MyApp::PostOnBuild;
use Moo::Role;
has id => (is => 'rwp');
has endpoint => (is => 'ro', default => sub { '/addresses' });
has requestor => (is => 'ro', default => sub { Net::Easypost::Request->new });
has field_names => (is => 'ro', builder => 1);
requires '_build_field_names';
requires 'serialize'; # or maybe just implement serialize within this role!
sub BUILD { }
after BUILD => sub {
my $self = shift;
my $resp = $self->requestor->post($self->endpoint, $self->serialize($self->field_names));
$self->_set_id( $resp->{id} );
};
my $adr = MyApp::Address->new(
street1 => '123 Example Lane',
city => 'Sydney',
state => 'NSW',
zip => '2035',
requestor => Test::Requestor->new,
);
谢谢,这真的很有帮助。我没有考虑过把这种逻辑放在Rolethaks中,这真的很有帮助。我没有考虑过把这种逻辑放在一个角色上