That's certainly one way to do it. It may be a good idea to factor out the BUILD
method into a role. Something like:
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} );
};
Now you classes don't need to define their own BUILD
method. All they need to do is:
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??
Note that requestor
is now an attribute, so when you're testing the class you can do something like:
my $adr = MyApp::Address->new(
street1 => '123 Example Lane',
city => 'Sydney',
state => 'NSW',
zip => '2035',
requestor => Test::Requestor->new,
);