@@ -4,6 +4,42 @@ class Schema
4
4
class Member
5
5
# Shared code for Object and Interface
6
6
module HasFields
7
+ class << self
8
+ # When this module is added to a class,
9
+ # add a place for that class's default behaviors
10
+ def self . extended ( child_class )
11
+ add_default_resolve_module ( child_class )
12
+ super
13
+ end
14
+
15
+ def add_default_resolve_module ( child_class )
16
+ if child_class . instance_variable_get ( :@_default_resolve )
17
+ # This can happen when an object implements an interface,
18
+ # since that interface has the `included` hook above.
19
+ return
20
+ end
21
+
22
+ default_resolve_module = Module . new
23
+ child_class . instance_variable_set ( :@_default_resolve , default_resolve_module )
24
+ child_class . include ( default_resolve_module )
25
+ end
26
+ end
27
+
28
+ # When this is included into interfaces,
29
+ # add a place for default field behaviors
30
+ def included ( child_class )
31
+ HasFields . add_default_resolve_module ( child_class )
32
+ # Also, prepare a place for default field implementations
33
+ super
34
+ end
35
+
36
+ # When a subclass of objects are created,
37
+ # add a place for that subclass's default field behaviors
38
+ def inherited ( child_class )
39
+ HasFields . add_default_resolve_module ( child_class )
40
+ super
41
+ end
42
+
7
43
# Add a field to this object or interface with the given definition
8
44
# @see {GraphQL::Schema::Field#initialize} for method signature
9
45
# @return [void]
@@ -31,15 +67,23 @@ def fields
31
67
# @return [void]
32
68
def add_field ( field_defn )
33
69
own_fields [ field_defn . name ] = field_defn
34
- if defined? ( self ::DefaultResolve )
35
- field_key = field_defn . name . inspect
36
- self ::DefaultResolve . module_eval <<-RUBY , __FILE__ , __LINE__ + 1
37
- def #{ field_defn . method_sym } (**args)
38
- field_inst = self.class.fields[#{ field_key } ] || raise(%|Failed to find field #{ field_key } for \# {self.class} among \# {self.class.fields.keys}|)
39
- field_inst.resolve_field_method(self, args, context)
40
- end
41
- RUBY
70
+ # Add a `super` method for implementing this field:
71
+ field_key = field_defn . name . inspect
72
+ default_resolve_module = self . instance_variable_get ( :@_default_resolve )
73
+ if default_resolve_module . nil?
74
+ # This should have been set up in one of the inherited or included hooks above,
75
+ # if it wasn't, it's because those hooks weren't called because `super` wasn't present.
76
+ raise <<-ERR
77
+ Uh oh! #{ self } doesn't have a default resolve module. This probably means that an `inherited` hook didn't call super.
78
+ Check `inherited` on #{ self } 's superclasses.
79
+ ERR
42
80
end
81
+ default_resolve_module . module_eval <<-RUBY , __FILE__ , __LINE__ + 1
82
+ def #{ field_defn . method_sym } (**args)
83
+ field_inst = self.class.fields[#{ field_key } ] || raise(%|Failed to find field #{ field_key } for \# {self.class} among \# {self.class.fields.keys}|)
84
+ field_inst.resolve_field_method(self, args, context)
85
+ end
86
+ RUBY
43
87
nil
44
88
end
45
89
0 commit comments