Skip to content

Commit 7f13fd5

Browse files
committed
feat(Schema) add field map for field lookups
1 parent 9d4b6c1 commit 7f13fd5

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

lib/graphql/schema.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require "graphql/schema/catchall_middleware"
22
require "graphql/schema/invalid_type_error"
3+
require "graphql/schema/instrumented_field_map"
34
require "graphql/schema/middleware_chain"
45
require "graphql/schema/possible_types"
56
require "graphql/schema/rescue_middleware"
@@ -108,6 +109,14 @@ def remove_handler(*args, &block)
108109
def define(**kwargs, &block)
109110
super
110111
types
112+
@instrumented_field_map = InstrumentedFieldMap.new(self)
113+
types.each do |type_name, type|
114+
if type.kind.fields?
115+
type.all_fields.each do |field_defn|
116+
@instrumented_field_map.set(type.name, field_defn.name, field_defn)
117+
end
118+
end
119+
end
111120
# Assert that all necessary configs are present:
112121
validation_error = Validation.validate(self)
113122
validation_error && raise(NotImplementedError, validation_error)
@@ -139,8 +148,7 @@ def execute(*args)
139148
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
140149
def get_field(parent_type, field_name)
141150
ensure_defined
142-
143-
defined_field = parent_type.get_field(field_name)
151+
defined_field = @instrumented_field_map.get(parent_type.name, field_name)
144152
if defined_field
145153
defined_field
146154
elsif field_name == "__typename"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module GraphQL
2+
class Schema
3+
# A two-level map with fields as the last values.
4+
# The first level is type names, which point to a second map.
5+
# The second level is field names, which point to fields.
6+
#
7+
# The catch is, the fields in this map _may_ have been modified by being instrumented.
8+
class InstrumentedFieldMap
9+
def initialize(schema)
10+
@storage = Hash.new { |h, k| h[k] = {} }
11+
end
12+
13+
def set(type_name, field_name, field)
14+
@storage[type_name][field_name] = field
15+
end
16+
17+
def get(type_name, field_name)
18+
type = @storage[type_name]
19+
type && type[field_name]
20+
end
21+
end
22+
end
23+
end

0 commit comments

Comments
 (0)