Skip to content

Commit a14df9b

Browse files
author
Robert Mosolgo
authored
Merge pull request #3069 from rmosolgo/better-method-warnings
Improve method conflict warnings
2 parents e4ff380 + 6bd4973 commit a14df9b

File tree

5 files changed

+50
-5
lines changed

5 files changed

+50
-5
lines changed

lib/graphql/schema/member/has_fields.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ def get_field(field_name)
5858
# Register this field with the class, overriding a previous one if needed.
5959
# @param field_defn [GraphQL::Schema::Field]
6060
# @return [void]
61-
def add_field(field_defn)
62-
if CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) && field_defn.original_name == field_defn.resolver_method && field_defn.method_conflict_warning?
63-
warn "#{self.graphql_name}'s `field :#{field_defn.name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`). Or use `method_conflict_warning: false` to suppress this warning."
61+
def add_field(field_defn, method_conflict_warning: field_defn.method_conflict_warning?)
62+
# Check that `field_defn.original_name` equals `resolver_method` and `method_sym` --
63+
# that shows that no override value was given manually.
64+
if method_conflict_warning && CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) && field_defn.original_name == field_defn.resolver_method && field_defn.original_name == field_defn.method_sym
65+
warn(conflict_field_name_warning(field_defn))
6466
end
6567
own_fields[field_defn.name] = field_defn
6668
nil
@@ -92,6 +94,14 @@ def global_id_field(field_name)
9294
def own_fields
9395
@own_fields ||= {}
9496
end
97+
98+
private
99+
100+
# @param [GraphQL::Schema::Field]
101+
# @return [String] A warning to give when this field definition might conflict with a built-in method
102+
def conflict_field_name_warning(field_defn)
103+
"#{self.graphql_name}'s `field :#{field_defn.original_name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`). Or use `method_conflict_warning: false` to suppress this warning."
104+
end
95105
end
96106
end
97107
end

lib/graphql/schema/mutation.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ def visible?(context)
7878

7979
private
8080

81+
def conflict_field_name_warning(field_defn)
82+
"#{self.graphql_name}'s `field :#{field_defn.name}` conflicts with a built-in method, use `hash_key:` or `method:` to pick a different resolve behavior for this field (for example, `hash_key: :#{field_defn.resolver_method}_value`, and modify the return hash). Or use `method_conflict_warning: false` to suppress this warning."
83+
end
84+
8185
# Override this to attach self as `mutation`
8286
def generate_payload_type
8387
payload_class = super

lib/graphql/schema/resolver/has_payload_type.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ def generate_payload_type
5858
resolver_fields.each do |name, f|
5959
# Reattach the already-defined field here
6060
# (The field's `.owner` will still point to the mutation, not the object type, I think)
61-
add_field(f)
61+
# Don't re-warn about a method conflict. Since this type is generated, it should be fixed in the resolver instead.
62+
add_field(f, method_conflict_warning: false)
6263
end
6364
end
6465
end

spec/graphql/schema/mutation_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,25 @@
165165
assert override_mutation.field_options[:null]
166166
end
167167
end
168+
169+
it "warns once for possible conflict methods" do
170+
expected_warning = "X's `field :module` conflicts with a built-in method, use `hash_key:` or `method:` to pick a different resolve behavior for this field (for example, `hash_key: :module_value`, and modify the return hash). Or use `method_conflict_warning: false` to suppress this warning.\n"
171+
assert_output "", expected_warning do
172+
# This should warn:
173+
mutation = Class.new(GraphQL::Schema::Mutation) do
174+
graphql_name "X"
175+
field :module, String, null: true
176+
end
177+
# This should not warn again, when generating the payload type with the same fields:
178+
mutation.payload_type
179+
end
180+
181+
assert_output "", "" do
182+
mutation = Class.new(GraphQL::Schema::Mutation) do
183+
graphql_name "X"
184+
field :module, String, null: true, hash_key: :module_value
185+
end
186+
mutation.payload_type
187+
end
188+
end
168189
end

spec/graphql/schema/object_spec.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ def call(o, a, c)
357357
end
358358
end
359359

360-
it "doesn't warn with an override" do
360+
it "doesn't warn with a resolver_method: override" do
361361
assert_output "", "" do
362362
Class.new(GraphQL::Schema::Object) do
363363
graphql_name "X"
@@ -366,6 +366,15 @@ def call(o, a, c)
366366
end
367367
end
368368

369+
it "doesn't warn with a method: override" do
370+
assert_output "", "" do
371+
Class.new(GraphQL::Schema::Object) do
372+
graphql_name "X"
373+
field :module, String, null: true, method: :mod
374+
end
375+
end
376+
end
377+
369378
it "doesn't warn with a suppression" do
370379
assert_output "", "" do
371380
Class.new(GraphQL::Schema::Object) do

0 commit comments

Comments
 (0)