Fix method names clash in Moose Role

When flattening all endpoint API methods into a single class, some
method names may clash, e.g. every API has a new() method. So we skip
them, they must be accessed via the API method. Warnings are emitted to
document skipped methods.
This commit is contained in:
Dave Baird
2015-11-08 21:51:26 +01:00
parent 6a5f583ab0
commit f0f43f5fdf
6 changed files with 143 additions and 20 deletions

View File

@@ -4,7 +4,7 @@ use utf8;
use Moose::Role;
use namespace::autoclean;
use Class::Inspector;
use Log::Any qw($log);
use WWW::SwaggerClient::ApiFactory;
requires 'auth_setup_handler';
@@ -23,21 +23,41 @@ has api_factory => ( is => 'ro',
sub BUILD {
my $self = shift;
my %outsiders = map {$_ => 1} qw( croak );
# ignore these symbols imported into API namespaces
my %outsiders = map {$_ => 1} qw( new croak );
foreach my $name ($self->api_factory->apis_available) {
my $att_name = sprintf "%s_api", lc($name);
my $api_class = $self->api_factory->classname_for($name);
my %delegates;
# collect the methods callable on each API
foreach my $api_name ($self->api_factory->apis_available) {
my $api_class = $self->api_factory->classname_for($api_name);
my $methods = Class::Inspector->methods($api_class, 'expanded');
my @local_methods = grep {! $outsiders{$_}} map {$_->[2]} grep {$_->[1] eq $api_class} @$methods;
push( @{$delegates{$_}}, {api_name => $api_name, api_class => $api_class} ) for @local_methods;
}
# remove clashes
foreach my $method (keys %delegates) {
if ( @{$delegates{$method}} > 1 ) {
my ($apis) = delete $delegates{$method};
foreach my $api (@$apis) {
warn sprintf "Cannot delegate %s (use \$self->%s_api->%s instead)\n", $method, lc($api->{api_name}), $method;
}
}
}
# build the flattened API
foreach my $api_name ($self->api_factory->apis_available) {
my $att_name = sprintf "%s_api", lc($api_name);
my $api_class = $self->api_factory->classname_for($api_name);
my @delegated = grep { $delegates{$_}->[0]->{api_name} eq $api_name } keys %delegates;
$log->debugf("Adding API: '%s' handles %s", $att_name, join ', ', @delegated);
$self->meta->add_attribute( $att_name => (
is => 'ro',
isa => $api_class,
default => sub {$self->api_factory->get_api($name)},
default => sub {$self->api_factory->get_api($api_name)},
lazy => 1,
handles => \@local_methods,
handles => \@delegated,
) );
}
}