Skip to content

Commit e81135e

Browse files
author
Robert Mosolgo
authored
Merge pull request #3471 from rmosolgo/fix-rescue-from-on-loading-arguments
Fix rescue from on loading arguments
2 parents 82b823e + 4f65937 commit e81135e

File tree

5 files changed

+83
-3
lines changed

5 files changed

+83
-3
lines changed

lib/graphql/query/null_context.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ def visible_field?(t); true; end
99
def visible_type?(t); true; end
1010
end
1111

12+
class NullQuery
13+
def with_error_handling
14+
yield
15+
end
16+
end
17+
1218
attr_reader :schema, :query, :warden, :dataloader
1319

1420
def initialize
15-
@query = nil
21+
@query = NullQuery.new
1622
@dataloader = GraphQL::Dataloader::NullDataloader.new
1723
@schema = GraphQL::Schema.new
1824
@warden = NullWarden.new(

lib/graphql/schema/argument.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,9 @@ def coerce_into_values(parent_object, values, context, argument_values)
266266
loaded_values = coerced_value.map { |val| owner.load_application_object(self, loads, val, context) }
267267
context.schema.after_any_lazies(loaded_values) { |result| result }
268268
else
269-
owner.load_application_object(self, loads, coerced_value, context)
269+
context.query.with_error_handling do
270+
owner.load_application_object(self, loads, coerced_value, context)
271+
end
270272
end
271273
end
272274

lib/graphql/schema/scalar.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ def default_scalar?
4444
def validate_non_null_input(value, ctx)
4545
result = Query::InputValidationResult.new
4646
coerced_result = begin
47-
coerce_input(value, ctx)
47+
ctx.query.with_error_handling do
48+
coerce_input(value, ctx)
49+
end
4850
rescue GraphQL::CoercionError => err
4951
err
5052
end

lib/graphql/static_validation/validator.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ def validate(query, validate: true, timeout: nil)
7373
irep: irep,
7474
}
7575
end
76+
rescue GraphQL::ExecutionError => e
77+
{
78+
errors: [e],
79+
irep: nil,
80+
}
7681
end
7782

7883
# Invoked when static validation times out.

spec/graphql/execution/errors_spec.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def self.authorized?(obj, ctx)
5656
if ctx[:authorized] == false
5757
raise ErrorD
5858
end
59+
true
5960
end
6061

6162
field :string, String, null: false
@@ -76,6 +77,16 @@ def self.object_from_id(type, value, ctx)
7677
end
7778
end
7879

80+
class PickyString < GraphQL::Schema::Scalar
81+
def self.coerce_input(value, ctx)
82+
if value == "picky"
83+
value
84+
else
85+
raise ErrorB, "The string wasn't \"picky\""
86+
end
87+
end
88+
end
89+
7990
class Query < GraphQL::Schema::Object
8091
field :f1, Int, null: true do
8192
argument :a1, Int, required: false
@@ -116,6 +127,22 @@ def f7
116127
raise ErrorBGrandchildClass
117128
end
118129

130+
field :f8, String, null: true do
131+
argument :input, PickyString, required: true
132+
end
133+
134+
def f8(input:)
135+
input
136+
end
137+
138+
field :f9, String, null: true do
139+
argument :thing_id, ID, required: true, loads: Thing
140+
end
141+
142+
def f9(thing:)
143+
thing[:id]
144+
end
145+
119146
field :thing, Thing, null: true
120147
def thing
121148
:thing
@@ -133,6 +160,18 @@ def non_nullable_array
133160

134161
query(Query)
135162
lazy_resolve(Proc, :call)
163+
164+
def self.object_from_id(id, ctx)
165+
if id == "boom"
166+
raise ErrorB
167+
end
168+
169+
{ thing: true, id: id }
170+
end
171+
172+
def self.resolve_type(type, obj, ctx)
173+
Thing
174+
end
136175
end
137176

138177
class ErrorsTestSchemaWithoutInterpreter < GraphQL::Schema
@@ -198,6 +237,32 @@ def non_nullable_array
198237
assert_equal ["raised subclass (ErrorsTestSchema::Query.f5, nil, {})"], context[:errors]
199238
end
200239

240+
describe "errors raised when coercing inputs" do
241+
it "rescues them" do
242+
res1 = ErrorsTestSchema.execute("{ f8(input: \"picky\") }")
243+
assert_equal "picky", res1["data"]["f8"]
244+
res2 = ErrorsTestSchema.execute("{ f8(input: \"blah\") }")
245+
assert_equal ["errors"], res2.keys
246+
assert_equal ["boom!"], res2["errors"].map { |e| e["message"] }
247+
248+
res3 = ErrorsTestSchema.execute("query($v: PickyString!) { f8(input: $v) }", variables: { v: "blah" })
249+
assert_equal ["errors"], res3.keys
250+
assert_equal ["Variable $v of type PickyString! was provided invalid value"], res3["errors"].map { |e| e["message"] }
251+
assert_equal [["boom!"]], res3["errors"].map { |e| e["extensions"]["problems"].map { |pr| pr["explanation"] } }
252+
end
253+
end
254+
255+
describe "errors raised when loading objects from ID" do
256+
it "rescues them" do
257+
res1 = ErrorsTestSchema.execute("{ f9(thingId: \"abc\") }")
258+
pp res1
259+
assert_equal "abc", res1["data"]["f9"]
260+
261+
res2 = ErrorsTestSchema.execute("{ f9(thingId: \"boom\") }")
262+
assert_equal ["boom!"], res2["errors"].map { |e| e["message"] }
263+
end
264+
end
265+
201266
describe "errors raised in authorized hooks" do
202267
it "rescues them" do
203268
context = { authorized: false }

0 commit comments

Comments
 (0)