Skip to content

Commit dc06a16

Browse files
committed
Eliminate runtime .is_a? checks from HasInterfaces
1 parent 4712a3d commit dc06a16

3 files changed

Lines changed: 49 additions & 25 deletions

File tree

lib/graphql/schema/member/has_interfaces.rb

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,37 @@ def own_interface_type_memberships
5555
end
5656

5757
def interface_type_memberships
58-
own_tms = own_interface_type_memberships
59-
if (self.is_a?(Class) && superclass.respond_to?(:interface_type_memberships))
60-
inherited_tms = superclass.interface_type_memberships
61-
if inherited_tms.size > 0
62-
own_tms + inherited_tms
63-
else
64-
own_tms
58+
own_interface_type_memberships
59+
end
60+
61+
module ClassConfigured
62+
# This combination of extended -> inherited -> extended
63+
# means that the base class (`Schema::Object`) *won't*
64+
# have the superclass-related code in `InheritedInterfaces`,
65+
# but child classes of `Schema::Object` will have it.
66+
# That way, we don't need a `superclass.respond_to?(...)` check.
67+
def inherited(child_class)
68+
super
69+
child_class.extend(InheritedInterfaces)
70+
end
71+
72+
module InheritedInterfaces
73+
def interfaces(context = GraphQL::Query::NullContext)
74+
visible_interfaces = super
75+
visible_interfaces.concat(superclass.interfaces(context))
76+
visible_interfaces.uniq!
77+
visible_interfaces
78+
end
79+
80+
def interface_type_memberships
81+
own_tms = super
82+
inherited_tms = superclass.interface_type_memberships
83+
if inherited_tms.size > 0
84+
own_tms + inherited_tms
85+
else
86+
own_tms
87+
end
6588
end
66-
else
67-
own_tms
6889
end
6990
end
7091

@@ -73,28 +94,29 @@ def interfaces(context = GraphQL::Query::NullContext)
7394
warden = Warden.from_context(context)
7495
visible_interfaces = []
7596
own_interface_type_memberships.each do |type_membership|
76-
# During initialization, `type_memberships` can hold late-bound types
7797
case type_membership
78-
when String, Schema::LateBoundType
79-
visible_interfaces << type_membership
8098
when Schema::TypeMembership
8199
if warden.visible_type_membership?(type_membership, context)
82100
visible_interfaces << type_membership.abstract_type
83101
end
102+
when String, Schema::LateBoundType
103+
# During initialization, `type_memberships` can hold late-bound types
104+
visible_interfaces << type_membership
84105
else
85106
raise "Invariant: Unexpected type_membership #{type_membership.class}: #{type_membership.inspect}"
86107
end
87108
end
109+
visible_interfaces.uniq!
88110

89-
if self.is_a?(Class) && superclass <= GraphQL::Schema::Object
90-
visible_interfaces.concat(superclass.interfaces(context))
91-
end
92-
93-
visible_interfaces.uniq
111+
visible_interfaces
94112
end
95113

96114
private
97115

116+
def self.extended(child_class)
117+
child_class.extend(ClassConfigured)
118+
end
119+
98120
def inherited(subclass)
99121
super
100122
subclass.class_eval do

spec/graphql/schema/interface_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ def thing
336336
end
337337
interfaces_names = thing_type["interfaces"].map { |i| i["name"] }.sort
338338

339-
assert_equal interfaces_names, ["Named", "Node", "Timestamped"]
339+
assert_equal ["Named", "Node", "Timestamped"], interfaces_names
340340
end
341341
end
342342

spec/graphql/schema/object_spec.rb

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@
4040
# one more than the parent class
4141
assert_equal 10, new_object_class.fields.size
4242
# inherited interfaces are present
43-
assert_equal [
44-
"GloballyIdentifiable",
45-
"HasMusicians",
46-
"InvisibleNameEntity",
47-
"NamedEntity",
48-
"PrivateNameEntity",
49-
], new_object_class.interfaces.map(&:graphql_name).sort
43+
expected_interface_names = [
44+
"GloballyIdentifiable",
45+
"HasMusicians",
46+
"InvisibleNameEntity",
47+
"NamedEntity",
48+
"PrivateNameEntity",
49+
]
50+
assert_equal expected_interface_names, object_class.interfaces.map(&:graphql_name).sort
51+
assert_equal expected_interface_names, new_object_class.interfaces.map(&:graphql_name).sort
5052
# The new field is present
5153
assert new_object_class.fields.key?("newField")
5254
# The overridden field is present:

0 commit comments

Comments
 (0)