Skip to content

Instantly share code, notes, and snippets.

@taiyoh
Created April 27, 2018 02:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taiyoh/c9aa7a6db938d4f0ad9abae4e25836a5 to your computer and use it in GitHub Desktop.
Save taiyoh/c9aa7a6db938d4f0ad9abae4e25836a5 to your computer and use it in GitHub Desktop.
#!perl
use 5.014;
use warnings;
use GraphQL::Schema;
use GraphQL::Execution qw/execute/;
use Data::Dumper;
package Person {
use Moo; # GraphQLがMoo依存なので使わせてもらう
has name => (
is => 'ro',
required => 1,
);
has favorite_fruit_ids => (
is => 'ro',
required => 1,
);
};
package Fruit {
use Moo;
has id => (
is => 'ro',
required => 1,
);
has name => (
is => 'ro',
required => 1,
);
};
package MyApp::GraphQL::Resolver::Query {
sub person {
my ($root_value, $args, $context, $info) = @_;
my $person = main::get_person();
return { name => $person->name, favorite_fruit_ids => $person->favorite_fruit_ids };
}
};
package MyApp::GraphQL::Resolver::Person {
sub favoriteFruits {
my ($root_value, $args, $context, $info) = @_;
my $fruits = main::get_fruits($root_value->{favorite_fruit_ids});
return [ map +{ name => $_->name }, @$fruits ];
}
};
my $idx = 1;
my @fruits = map { Fruit->new(id => $idx++, name => $_) } qw/apple banana orange grape kiwifruit/;
my $person = Person->new(name => 'taiyoh', favorite_fruit_ids => [1, 5]);
sub get_person { $person }
sub get_fruits {
my $ids = shift;
my %id_map = map { $_ => 1 } @$ids;
return [ grep { $id_map{$_->id} } @fruits ];
}
my $schema = GraphQL::Schema->from_doc(<<'EOF');
type Person {
name: String!
favoriteFruits: [Fruit!]!
}
type Fruit {
name: String!
}
type Query {
person: Person
}
schema {
query: Query
}
EOF
my $query = <<'EOQ';
{
person {
name
favoriteFruits {
name
}
}
}
EOQ
my $res = execute(
$schema,
$query,
{}, # root_value
{}, # context_value
{}, # variables
undef, # operation_name,
sub { # resolver
my ($root_value, $args, $context, $info) = @_;
my $field_name = $info->{field_name};
my $parent_type = $info->{parent_type}->name;
my $pkg = sprintf('MyApp::GraphQL::Resolver::%s', $parent_type);
if (my $resolver = $pkg->can($field_name)) {
return $resolver->($root_value, $args, $context, $info);
}
# https://metacpan.org/source/ETJ/GraphQL-0.26/lib/GraphQL/Execution.pm#L668-688 より
my $root_ref = ref $root_value;
if ($root_ref eq 'CODE') {
return $root_value->($args, $context, $info);
} elsif ($root_ref ne 'HASH' && $root_value->can($field_name)) {
return $root_value->$field_name($args, $context, $info);
}
return $root_value->{$field_name};
}
);
local $Data::Dumper::Indent = 1;
say Dumper($res);
__END__
$VAR1 = {
'data' => {
'person' => {
'favoriteFruits' => [
{
'name' => 'apple'
},
{
'name' => 'kiwifruit'
}
],
'name' => 'taiyoh'
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment