Skip to content

Commit a577648

Browse files
committed
Support resolver config parameters when configuring it for use.
Previously, we supported resolver parameters provided when registering the resolver, but it's quite useful to be able to provide them when configuring a type or field to use a resolver. This allows resolver params to be provided in all 3 spots.
1 parent 64a2a98 commit a577648

14 files changed

Lines changed: 88 additions & 39 deletions

File tree

config/site/examples/custom_resolver/lib/roll_dice_resolver.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
class RollDiceResolver
1212
def initialize(elasticgraph_graphql:, config:)
1313
@number_of_dice = config.fetch(:number_of_dice)
14+
@multiplier = config.fetch(:multiplier)
1415
end
1516

1617
def resolve(field:, object:, args:, context:)
1718
@number_of_dice
1819
.times
1920
.map { rand(args.fetch("sides")) + 1 }
20-
.sum
21+
.sum * @multiplier
2122
end
2223
end
2324
# :snippet-end:

config/site/examples/custom_resolver/schema.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
f.argument "sides", "Int" do |a|
2626
a.default 6
2727
end
28-
f.resolve_with :roll_dice
28+
f.resolve_with :roll_dice, multiplier: 3
2929
end
3030
end
3131
# :snippet-end:

config/site/examples/custom_resolver/validate.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
response = graphql.graphql_query_executor.execute(query)
1717
data = response.fetch("data")
1818

19-
unless (1..12).cover?(data.fetch("roll6SidedDice")) && (1..20).cover?(data.fetch("roll10SidedDice"))
19+
unless (3..36).cover?(data.fetch("roll6SidedDice")) && (3..60).cover?(data.fetch("roll10SidedDice"))
2020
raise <<~EOS
2121
Got an unexpected response:
2222

config/site/src/guides/custom-graphql-resolvers.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ which allows you to inspect the child field selections. However, providing it im
5050
more performant if you omit it from your `resolve` definition.
5151

5252
In this case, our `RollDiceResolver` simulates the rolling of the configured `number_of_dice`, each of which has a number of `sides`
53-
provided as a query argument.
53+
provided as a query argument. Finally, it multiplies the dice roll by a configured `multiplier`.
5454

5555
### Step 2: Register the Resolver
5656

@@ -66,7 +66,13 @@ In this case, we've registered the resolver to roll two dice.
6666
{% include copyable_code_snippet.html language="ruby" data="custom_resolver.snippets.schema_rb.on_root_query_type" %}
6767

6868
Here we've defined a field on `Query` using [`on_root_query_type`](/elasticgraph/api-docs/{{ site.data.doc_versions.latest_version }}/ElasticGraph/SchemaDefinition/API.html#on_root_query_type-instance_method),
69-
and configured it to use the `:roll_dice` resolver.
69+
and configured it to use the `:roll_dice` resolver. Extra arguments (`multiplier: 3`, in this case) will be passed to the resolver in `config`.
70+
71+
{: .alert-note}
72+
**Note**{: .alert-title}
73+
Resolver config values can be provided both when registering the resolver (via `schema.register_graphql_resolver`)
74+
and when configuring a field to use the resolver (via `field.resolve_with`). These configuration options will be
75+
merged together to provide `config` when instantiating the resolver.
7076

7177
### Step 4: Query the Custom Field
7278

elasticgraph-graphql/lib/elastic_graph/graphql.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,13 @@ def resolver_query_adapter
183183
def named_graphql_resolvers
184184
@named_graphql_resolvers ||= runtime_metadata.graphql_resolvers_by_name.transform_values do |resolver|
185185
ext = resolver.load_resolver
186-
(_ = ext.extension_class).new(elasticgraph_graphql: self, config: ext.config)
186+
187+
->(field_config) do
188+
(_ = ext.extension_class).new(
189+
elasticgraph_graphql: self,
190+
config: ext.config.merge(field_config)
191+
)
192+
end
187193
end
188194
end
189195

elasticgraph-graphql/lib/elastic_graph/graphql/resolvers/graphql_adapter_builder.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ module Resolvers
1717
class GraphQLAdapterBuilder
1818
def initialize(runtime_metadata:, named_resolvers:, query_adapter:)
1919
@runtime_metadata = runtime_metadata
20-
@named_resolvers = named_resolvers
20+
@resolvers_by_name_and_field_config = named_resolvers.transform_values do |resolver_constructor|
21+
::Hash.new do |hash, field_config|
22+
hash[field_config] = resolver_constructor.call(field_config)
23+
end
24+
end
2125
@query_adapter = query_adapter
2226
end
2327

@@ -43,9 +47,9 @@ def object_type_hash
4347
@runtime_metadata.object_types_by_name.filter_map do |type_name, type|
4448
fields_hash = type.graphql_fields_by_name.filter_map do |field_name, field|
4549
if (configured_resolver = field.resolver)
46-
resolver = @named_resolvers.fetch(configured_resolver.name) do
50+
resolver = @resolvers_by_name_and_field_config.fetch(configured_resolver.name) do
4751
raise Errors::SchemaError, "Resolver `#{configured_resolver.name}` (for `#{type_name}.#{field_name}`) cannot be found."
48-
end
52+
end[configured_resolver.config]
4953

5054
resolver_lambda =
5155
if resolver.method(:resolve).parameters.include?([:keyreq, :lookahead])

elasticgraph-graphql/sig/elastic_graph/graphql.rbs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module ElasticGraph
22
class GraphQL
3+
type namedGraphQLResolversHash = ::Hash[::Symbol, ^(::Hash[::Symbol, untyped]) -> resolver]
4+
35
attr_reader config: Config
46
attr_reader logger: ::Logger
57
attr_reader runtime_metadata: SchemaArtifacts::RuntimeMetadata::Schema
@@ -45,8 +47,8 @@ module ElasticGraph
4547
@resolver_query_adapter: Resolvers::QueryAdapter?
4648
def resolver_query_adapter: () -> Resolvers::QueryAdapter
4749

48-
@named_graphql_resolvers: ::Hash[::Symbol, resolver]?
49-
def named_graphql_resolvers: () -> ::Hash[::Symbol, resolver]
50+
@named_graphql_resolvers: namedGraphQLResolversHash?
51+
def named_graphql_resolvers: () -> namedGraphQLResolversHash
5052

5153
@datastore_query_adapters: ::Array[_QueryAdapter]?
5254
def datastore_query_adapters: () -> ::Array[_QueryAdapter]

elasticgraph-graphql/sig/elastic_graph/graphql/resolvers/graphql_adapter_builder.rbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ module ElasticGraph
77

88
class GraphQLAdapterBuilder
99
@runtime_metadata: SchemaArtifacts::RuntimeMetadata::Schema
10-
@named_resolvers: ::Hash[::Symbol, resolver]
10+
@resolvers_by_name_and_field_config: ::Hash[::Symbol, ::Hash[::Hash[::Symbol, untyped], resolver]]
1111
@query_adapter: QueryAdapter
1212

1313
def initialize: (
1414
runtime_metadata: SchemaArtifacts::RuntimeMetadata::Schema,
15-
named_resolvers: ::Hash[::Symbol, resolver],
15+
named_resolvers: namedGraphQLResolversHash,
1616
query_adapter: QueryAdapter
1717
) -> void
1818

elasticgraph-graphql/spec/support/query_adapter.rb

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,6 @@ class QueryProbe
2727
def initialize(list_item_count: 1)
2828
@list_item_count = list_item_count
2929
@graphql = yield(graphql_adapter: self)
30-
31-
# Only 2 resolvers yield to `Resolvers::GraphQLAdapter` to get a query built. Here we
32-
# put those into an array so that we can mimic the behavior in this `QueryProbe` and only
33-
# build an `DatastoreQuery` for the same fields.
34-
resolvers_module = ::ElasticGraph::GraphQL::Resolvers
35-
36-
@resolvers_that_build_datastore_query = @graphql.named_graphql_resolvers.values.select do |resolver|
37-
case resolver
38-
when resolvers_module::ListRecords, resolvers_module::NestedRelationships
39-
true
40-
else
41-
false
42-
end
43-
end
4430
end
4531

4632
def datastore_queries_by_field_for(query)
@@ -83,8 +69,8 @@ def call(parent_type, field, object, args, context)
8369
end
8470

8571
def resolved_with_resolver_that_builds_datastore_query?(schema_field, object)
86-
resolver = @graphql.named_graphql_resolvers.fetch(schema_field.resolver.name)
87-
@resolvers_that_build_datastore_query.include?(resolver)
72+
# Only 2 resolvers yield to `Resolvers::GraphQLAdapter` to get a query built.
73+
[:list_records, :nested_relationships].include?(schema_field.resolver.name)
8874
end
8975

9076
def coerce_input(type, value, ctx)

elasticgraph-schema_definition/lib/elastic_graph/schema_definition/api.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,22 +300,29 @@ def register_graphql_extension(extension_module, defined_at:, **config)
300300
# @param defined_at [String] the `require` path of the resolver
301301
# @param resolver_config [Hash<Symbol, Object>] configuration options for the resolver, to support parameterized resolvers
302302
# @return [void]
303+
# @see Mixins::HasIndices#resolve_fields_with
304+
# @see SchemaElements::Field#resolve_with
303305
#
304306
# @example Register a custom resolver for use by a custom `Query` field
305307
# # In `add_resolver.rb`:
306308
# class AddResolver
307309
# def initialize(elasticgraph_graphql:, config:)
310+
# @multiplier = config.fetch(:multiplier, 1)
308311
# end
309312
#
310313
# def resolve(field:, object:, args:, context:)
311-
# args.fetch("x") + args.fetch("y")
314+
# sum = args.fetch("x") + args.fetch("y")
315+
# sum * @multiplier
312316
# end
313317
# end
314318
#
315319
# # In `config/schema.rb`:
316320
# ElasticGraph.define_schema do |schema|
317321
# require(resolver_path = "add_resolver")
318-
# schema.register_graphql_resolver :add, AddResolver, defined_at: resolver_path
322+
# schema.register_graphql_resolver :add,
323+
# AddResolver,
324+
# defined_at: resolver_path,
325+
# multiplier: 2 # extra args are passed to the resolver within `config`.
319326
#
320327
# schema.on_root_query_type do |t|
321328
# t.field "add", "Int" do |f|

0 commit comments

Comments
 (0)