Skip to content

Commit 32f2e87

Browse files
committed
Make the skipped object available in rescue_from
1 parent 1a1c3a9 commit 32f2e87

File tree

2 files changed

+23
-8
lines changed

2 files changed

+23
-8
lines changed

lib/graphql/execution/interpreter/runtime.rb

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,19 @@ class Interpreter
1010
class Runtime
1111

1212
module GraphQLResult
13-
def initialize(result_name, parent_result)
13+
def initialize(result_name, parent_result, represented_value)
1414
@graphql_parent = parent_result
1515
if parent_result && parent_result.graphql_dead
1616
@graphql_dead = true
1717
end
1818
@graphql_result_name = result_name
1919
# Jump through some hoops to avoid creating this duplicate storage if at all possible.
2020
@graphql_metadata = nil
21+
@represented_value
2122
end
2223

2324
attr_accessor :graphql_dead
24-
attr_reader :graphql_parent, :graphql_result_name
25+
attr_reader :graphql_parent, :graphql_result_name, :represented_value
2526

2627
# Although these are used by only one of the Result classes,
2728
# it's handy to have the methods implemented on both (even though they just return `nil`)
@@ -41,14 +42,23 @@ def has_graphql_graph_parent_that_skips_list_items_that_raise
4142
!!graphql_parent&.has_graphql_graph_parent_that_skips_list_items_that_raise
4243
end
4344

45+
def find_first_skippable_object
46+
@first_skippable_object ||= if graphql_parent&.graphql_skip_list_items_that_raise
47+
self
48+
else
49+
graphql_parent&.find_first_skippable_parent
50+
end
51+
end
52+
4453
# @return [Hash] Plain-Ruby result data (`@graphql_metadata` contains Result wrapper objects)
4554
attr_accessor :graphql_result_data
4655
end
4756

4857
class GraphQLResultHash
49-
def initialize(_result_name, _parent_result)
58+
def initialize(result_name, parent_result, represented_value)
5059
super
5160
@graphql_result_data = {}
61+
@represented_value = represented_value
5262
end
5363

5464
include GraphQLResult
@@ -107,7 +117,7 @@ def [](k)
107117
class GraphQLResultArray
108118
include GraphQLResult
109119

110-
def initialize(_result_name, _parent_result)
120+
def initialize(_result_name, _parent_result, represented_value)
111121
super
112122
@graphql_result_data = []
113123
end
@@ -175,7 +185,7 @@ def initialize(query:)
175185
@multiplex_context = query.multiplex.context
176186
# Start this off empty:
177187
Thread.current[:__graphql_runtime_info] = nil
178-
@response = GraphQLResultHash.new(nil, nil)
188+
@response = GraphQLResultHash.new(nil, nil, nil)
179189
# Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
180190
@runtime_directive_names = []
181191
noop_resolve_owner = GraphQL::Schema::Directive.singleton_class
@@ -786,7 +796,7 @@ def continue_field(path, value, owner_type, field, current_type, ast_node, next_
786796
after_lazy(object_proxy, owner: current_type, path: path, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result) do |inner_object|
787797
continue_value = continue_value(path, inner_object, owner_type, field, is_non_null, ast_node, result_name, selection_result)
788798
if HALT != continue_value
789-
response_hash = GraphQLResultHash.new(result_name, selection_result)
799+
response_hash = GraphQLResultHash.new(result_name, selection_result, continue_value)
790800
set_result(selection_result, result_name, response_hash)
791801
gathered_selections = gather_selections(continue_value, current_type, next_selections)
792802
# There are two possibilities for `gathered_selections`:
@@ -828,7 +838,7 @@ def continue_field(path, value, owner_type, field, current_type, ast_node, next_
828838
# puts("Item type: #{inner_type}, #{inner_type.skip_nodes_on_raise?.inspect}")
829839
# This is true for objects, unions, and interfaces
830840
use_dataloader_job = !inner_type.unwrap.kind.input?
831-
response_list = GraphQLResultArray.new(result_name, selection_result)
841+
response_list = GraphQLResultArray.new(result_name, selection_result, value)
832842
response_list.graphql_non_null_list_items = inner_type.non_null?
833843
response_list.graphql_skip_list_items_that_raise = current_type.skip_nodes_on_raise?
834844
set_result(selection_result, result_name, response_list)

lib/graphql/query/context.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def []=(key, value)
207207

208208
def_delegators :@query, :trace, :interpreter?
209209

210-
RUNTIME_METADATA_KEYS = Set.new([:current_object, :current_arguments, :current_field, :current_path])
210+
RUNTIME_METADATA_KEYS = Set.new([:current_object, :current_arguments, :current_field, :current_path, :current_list_item_to_skip])
211211
# @!method []=(key, value)
212212
# Reassign `key` to the hash passed to {Schema#execute} as `context:`
213213

@@ -314,6 +314,11 @@ def scoped_set!(key, value)
314314
scoped_merge!(key => value)
315315
nil
316316
end
317+
318+
def can_skip_list_item?
319+
thread_info = Thread.current[:__graphql_runtime_info]
320+
thread_info && thread_info.key?(:current_list_item_to_skip)
321+
end
317322
end
318323
end
319324
end

0 commit comments

Comments
 (0)