Skip to content

Commit 0c83705

Browse files
committed
Fix super methods: don't add when there's already one
1 parent 47f62c9 commit 0c83705

File tree

2 files changed

+39
-27
lines changed

2 files changed

+39
-27
lines changed

lib/graphql/schema/member/has_fields.rb

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,10 @@ def fields
7272
# @return [void]
7373
def add_field(field_defn)
7474
own_fields[field_defn.name] = field_defn
75-
# Add a `super` method for implementing this field:
76-
field_key = field_defn.name.inspect
77-
default_resolve_module = self.instance_variable_get(:@_default_resolve)
78-
if default_resolve_module.nil?
79-
# This should have been set up in one of the inherited or included hooks above,
80-
# if it wasn't, it's because those hooks weren't called because `super` wasn't present.
81-
raise <<-ERR
82-
Uh oh! #{self} doesn't have a default resolve module. This probably means that an `inherited` hook didn't call super.
83-
Check `inherited` on #{self}'s superclasses.
84-
ERR
75+
if !method_defined?(field_defn.method_sym)
76+
# Only add the super method if there isn't one already.
77+
add_super_method(field_defn.name, field_defn.method_sym)
8578
end
86-
default_resolve_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
87-
def #{field_defn.method_sym}(**args)
88-
field_inst = self.class.fields[#{field_key}] || raise(%|Failed to find field #{field_key} for \#{self.class} among \#{self.class.fields.keys}|)
89-
field_inst.resolve_field_method(self, args, context)
90-
end
91-
RUBY
9279
nil
9380
end
9481

@@ -122,6 +109,28 @@ def build_field(*args, **kwargs, &block)
122109
kwargs[:owner] = self
123110
field_class.new(*args, **kwargs, &block)
124111
end
112+
113+
# Find the magic module for holding super methods,
114+
# and add a field named `method_name` for implementing the field
115+
# called `field_name`.
116+
# It will be the `super` method if the method is overwritten in the class definition.
117+
def add_super_method(field_key, method_name)
118+
default_resolve_module = @_default_resolve
119+
if default_resolve_module.nil?
120+
# This should have been set up in one of the inherited or included hooks above,
121+
# if it wasn't, it's because those hooks weren't called because `super` wasn't present.
122+
raise <<-ERR
123+
Uh oh! #{self} doesn't have a default resolve module. This probably means that an `inherited` hook didn't call super.
124+
Check `inherited` on #{self}'s superclasses.
125+
ERR
126+
end
127+
default_resolve_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
128+
def #{method_name}(**args)
129+
field_inst = self.class.fields[#{field_key}] || raise(%|Failed to find field #{field_key} for \#{self.class} among \#{self.class.fields.keys}|)
130+
field_inst.resolve_field_method(self, args, context)
131+
end
132+
RUBY
133+
end
125134
end
126135
end
127136
end

spec/graphql/schema/member/has_fields_spec.rb

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,22 @@ def string
5959
end
6060
end
6161

62+
class SubSubObjectWithStringField < SubObjectWithStringField
63+
field :string, String, null: false
64+
end
65+
6266
class Query < BaseObject
6367
field :int, Integer, null: false
6468
def int
6569
# This should call default resolution
6670
super * 2
6771
end
6872

69-
field :string1, ObjectWithStringField, null: false
70-
alias :string1 :object
71-
72-
field :string2, SubObjectWithStringField, null: false
73-
alias :string2 :object
74-
75-
field :float1, ObjectWithFloatField, null: false
76-
alias :float1 :object
77-
78-
field :float2, ObjectWithSubFloatField, null: false
79-
alias :float2 :object
73+
field :string1, ObjectWithStringField, null: false, method: :object
74+
field :string2, SubObjectWithStringField, null: false, method: :object
75+
field :string3, SubSubObjectWithStringField, null: false, method: :object
76+
field :float1, ObjectWithFloatField, null: false, method: :object
77+
field :float2, ObjectWithSubFloatField, null: false, method: :object
8078
end
8179

8280
class Schema < GraphQL::Schema
@@ -109,6 +107,11 @@ class Schema < GraphQL::Schema
109107
res = SuperTest::Schema.execute(" { string2 { string } }", root_value: {})
110108
assert_equal "GNIRTS A S'EREH", res["data"]["string2"]["string"]
111109
end
110+
111+
it "can get a super method from a newly-added field" do
112+
res = SuperTest::Schema.execute(" { string3 { string } }", root_value: {})
113+
assert_equal "GNIRTS A S'EREH", res["data"]["string3"]["string"]
114+
end
112115
end
113116

114117
describe "Interface methods" do

0 commit comments

Comments
 (0)