Skip to content

Commit d4901ac

Browse files
committed
Dry selection enumeration
1 parent b28d94f commit d4901ac

File tree

1 file changed

+33
-48
lines changed

1 file changed

+33
-48
lines changed

lib/graphql/execution/interpreter/runtime.rb

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,16 @@ def inspect
9191
"#<#{self.class.name} response=#{@response.inspect}>"
9292
end
9393

94+
def tap_or_each(obj_or_array)
95+
if obj_or_array.is_a?(Array)
96+
obj_or_array.each do |item|
97+
yield(item, true)
98+
end
99+
else
100+
yield(obj_or_array, false)
101+
end
102+
end
103+
94104
# This _begins_ the execution. Some deferred work
95105
# might be stored up in lazies.
96106
# @return [void]
@@ -116,38 +126,27 @@ def run_eager
116126
#
117127
# Otherwise, `gathered_selections` is a hash of selections which can be
118128
# directly evaluated and the results can be written right into the main response hash.
119-
if gathered_selections.is_a?(Array)
120-
gathered_selections.each do |selections|
129+
tap_or_each(gathered_selections) do |selections, is_selection_array|
130+
if is_selection_array
121131
selection_response = GraphQLResultHash.new
122-
@dataloader.append_job {
123-
set_all_interpreter_context(query.root_value, nil, nil, path)
124-
resolve_with_directives(object_proxy, selections.graphql_directives) do
125-
evaluate_selections(
126-
path,
127-
context.scoped_context,
128-
object_proxy,
129-
root_type,
130-
root_op_type == "mutation",
131-
selections,
132-
selection_response,
133-
@response,
134-
)
135-
end
136-
}
132+
final_response = @response
133+
else
134+
selection_response = @response
135+
final_response = nil
137136
end
138-
else
137+
139138
@dataloader.append_job {
140139
set_all_interpreter_context(query.root_value, nil, nil, path)
141-
resolve_with_directives(object_proxy, gathered_selections.graphql_directives) do
140+
resolve_with_directives(object_proxy, selections.graphql_directives) do
142141
evaluate_selections(
143142
path,
144143
context.scoped_context,
145144
object_proxy,
146145
root_type,
147146
root_op_type == "mutation",
148-
gathered_selections,
149-
@response,
150-
nil,
147+
selections,
148+
selection_response,
149+
final_response,
151150
)
152151
end
153152
}
@@ -599,53 +598,39 @@ def continue_field(path, value, owner_type, field, current_type, ast_node, next_
599598
response_hash.graphql_result_name = result_name
600599
set_result(selection_result, result_name, response_hash)
601600
gathered_selections = gather_selections(continue_value, current_type, next_selections)
602-
# I wish I could figure out how to DRY this...
603-
# Basically, there are two possibilities:
601+
# There are two possibilities for `gathered_selections`:
604602
# 1. All selections of this object should be evaluated together (there are no runtime directives modifying execution).
605603
# This case is handled below, and the result can be written right into the main `response_hash` above.
606604
# In this case, `gathered_selections` is a hash of selections.
607605
# 2. Some selections of this object have runtime directives that may or may not modify execution.
608606
# That part of the selection is evaluated in an isolated way, writing into a sub-response object which is
609607
# eventually merged into the final response. In this case, `gathered_selections` is an array of things to run in isolation.
610608
# (Technically, it's possible that one of those entries _doesn't_ require isolation.)
611-
if gathered_selections.is_a?(Array)
612-
gathered_selections.each do |selections|
609+
tap_or_each(gathered_selections) do |selections, is_selection_array|
610+
if is_selection_array
613611
this_result = GraphQLResultHash.new
614612
this_result.graphql_parent = selection_result
615613
this_result.graphql_result_name = result_name
616-
617-
set_all_interpreter_context(continue_value, nil, nil, path) # reset this mutable state
618-
resolve_with_directives(continue_value, selections.graphql_directives) do
619-
evaluate_selections(
620-
path,
621-
context.scoped_context,
622-
continue_value,
623-
current_type,
624-
false,
625-
selections,
626-
this_result,
627-
response_hash,
628-
)
629-
this_result
630-
end
614+
final_result = response_hash
615+
else
616+
this_result = response_hash
617+
final_result = nil
631618
end
632-
else
633619
set_all_interpreter_context(continue_value, nil, nil, path) # reset this mutable state
634-
resolve_with_directives(continue_value, gathered_selections.graphql_directives) do
620+
resolve_with_directives(continue_value, selections.graphql_directives) do
635621
evaluate_selections(
636622
path,
637623
context.scoped_context,
638624
continue_value,
639625
current_type,
640626
false,
641-
gathered_selections,
642-
response_hash,
643-
nil,
627+
selections,
628+
this_result,
629+
final_result,
644630
)
645-
response_hash
631+
this_result
646632
end
647633
end
648-
response_hash
649634
end
650635
end
651636
when "LIST"

0 commit comments

Comments
 (0)