Skip to content

Commit 81d9a12

Browse files
committed
Fix connection wrappers on lazy lists
1 parent 57f4a8d commit 81d9a12

File tree

2 files changed

+75
-36
lines changed

2 files changed

+75
-36
lines changed

lib/graphql/schema/field/connection_extension.rb

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,43 +22,49 @@ def resolve(object:, arguments:, context:)
2222
end
2323

2424
def after_resolve(value:, object:, arguments:, context:, memo:)
25-
if value.is_a? GraphQL::ExecutionError
26-
# This isn't even going to work because context doesn't have ast_node anymore
27-
context.add_error(value)
28-
nil
29-
elsif value.nil?
30-
nil
31-
elsif value.is_a?(GraphQL::Pagination::Connection)
32-
# update the connection with some things that may not have been provided
33-
value.context ||= context
34-
value.parent ||= object.object
35-
value.first_value ||= arguments[:first]
36-
value.after_value ||= arguments[:after]
37-
value.last_value ||= arguments[:last]
38-
value.before_value ||= arguments[:before]
39-
if field.has_max_page_size? && !value.has_max_page_size_override?
40-
value.max_page_size = field.max_page_size
25+
# rename some inputs to avoid conflicts inside the block
26+
maybe_lazy = value
27+
value = nil
28+
context.schema.after_lazy(maybe_lazy) do |resolved_value|
29+
value = resolved_value
30+
if value.is_a? GraphQL::ExecutionError
31+
# This isn't even going to work because context doesn't have ast_node anymore
32+
context.add_error(value)
33+
nil
34+
elsif value.nil?
35+
nil
36+
elsif value.is_a?(GraphQL::Pagination::Connection)
37+
# update the connection with some things that may not have been provided
38+
value.context ||= context
39+
value.parent ||= object.object
40+
value.first_value ||= arguments[:first]
41+
value.after_value ||= arguments[:after]
42+
value.last_value ||= arguments[:last]
43+
value.before_value ||= arguments[:before]
44+
if field.has_max_page_size? && !value.has_max_page_size_override?
45+
value.max_page_size = field.max_page_size
46+
end
47+
if (custom_t = context.schema.connections.edge_class_for_field(@field))
48+
value.edge_class = custom_t
49+
end
50+
value
51+
elsif context.schema.new_connections?
52+
wrappers = context.namespace(:connections)[:all_wrappers] ||= context.schema.connections.all_wrappers
53+
context.schema.connections.wrap(field, object.object, value, arguments, context, wrappers: wrappers)
54+
else
55+
if object.is_a?(GraphQL::Schema::Object)
56+
object = object.object
57+
end
58+
connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(value)
59+
connection_class.new(
60+
value,
61+
arguments,
62+
field: field,
63+
max_page_size: field.max_page_size,
64+
parent: object,
65+
context: context,
66+
)
4167
end
42-
if (custom_t = context.schema.connections.edge_class_for_field(@field))
43-
value.edge_class = custom_t
44-
end
45-
value
46-
elsif context.schema.new_connections?
47-
wrappers = context.namespace(:connections)[:all_wrappers] ||= context.schema.connections.all_wrappers
48-
context.schema.connections.wrap(field, object.object, value, arguments, context, wrappers: wrappers)
49-
else
50-
if object.is_a?(GraphQL::Schema::Object)
51-
object = object.object
52-
end
53-
connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(value)
54-
connection_class.new(
55-
value,
56-
arguments,
57-
field: field,
58-
max_page_size: field.max_page_size,
59-
parent: object,
60-
context: context,
61-
)
6268
end
6369
end
6470
end

spec/graphql/schema/member/scoped_spec.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ def self.scope_items(items, context)
1212
items.select { |i| i.name == "Trombone" }
1313
elsif context[:english]
1414
items.select { |i| i.name == "Paperclip" }
15+
elsif context[:lazy]
16+
# return everything, but make the runtime wait for it,
17+
# and add a flag for confirming it was called
18+
->() {
19+
context[:proc_called] = true
20+
items
21+
}
1522
else
1623
# boot everything
1724
items.reject { true }
@@ -105,6 +112,7 @@ def things
105112
use GraphQL::Execution::Interpreter
106113
use GraphQL::Analysis::AST
107114
end
115+
lazy_resolve(Proc, :call)
108116
end
109117

110118
describe ".scope_items(items, ctx)" do
@@ -177,6 +185,25 @@ def get_item_names_with_context(ctx, field_name: "items")
177185
assert_equal ["Paperclip"], names
178186
end
179187

188+
it "works for lazy connection values" do
189+
ctx = { lazy: true }
190+
query_str = "
191+
{
192+
itemsConnection {
193+
edges {
194+
node {
195+
name
196+
}
197+
}
198+
}
199+
}
200+
"
201+
res = ScopeSchema.execute(query_str, context: ctx)
202+
names = res["data"]["itemsConnection"]["edges"].map { |e| e["node"]["name"] }
203+
assert_equal ["Trombone", "Paperclip"], names
204+
assert_equal true, ctx[:proc_called]
205+
end
206+
180207
it "is called for abstract types" do
181208
query_str = "
182209
{
@@ -194,6 +221,12 @@ def get_item_names_with_context(ctx, field_name: "items")
194221
things = res["data"]["things"]
195222
assert_equal [{ "name" => "Trombone" }, {"designation" => "Turbine"}], things
196223
end
224+
225+
it "works with lazy values" do
226+
ctx = {lazy: true}
227+
assert_equal ["Trombone", "Paperclip"], get_item_names_with_context(ctx)
228+
assert_equal true, ctx[:proc_called]
229+
end
197230
end
198231

199232
describe "Schema::Field.scoped?" do

0 commit comments

Comments
 (0)