diff --git a/lib/graphql/schema/visibility.rb b/lib/graphql/schema/visibility.rb index de6be3d696..4ffe1be408 100644 --- a/lib/graphql/schema/visibility.rb +++ b/lib/graphql/schema/visibility.rb @@ -226,7 +226,9 @@ def load_all(types: nil) elsif member.respond_to?(:interface_type_memberships) member.interface_type_memberships.each do |itm| @all_references[itm.abstract_type] << member - @interface_type_memberships[itm.abstract_type] << itm + # `itm.object_type` may not actually be `member` if this implementation + # is inherited from a superclass + @interface_type_memberships[itm.abstract_type] << [itm, member] end elsif member < GraphQL::Schema::Union @unions_for_references << member @@ -275,13 +277,12 @@ def load_all(types: nil) # TODO: somehow don't iterate over all these, # only the ones that may have been modified - @interface_type_memberships.each do |int_type, type_memberships| + @interface_type_memberships.each do |int_type, type_membership_pairs| referers = @all_references[int_type].select { |r| r.is_a?(GraphQL::Schema::Field) } if !referers.empty? - type_memberships.each do |type_membership| - implementor_type = type_membership.object_type + type_membership_pairs.each do |(type_membership, impl_type)| # Add new items only: - @all_references[implementor_type] |= referers + @all_references[impl_type] |= referers end end end diff --git a/lib/graphql/schema/visibility/profile.rb b/lib/graphql/schema/visibility/profile.rb index 3f426d9b86..b88027e5c5 100644 --- a/lib/graphql/schema/visibility/profile.rb +++ b/lib/graphql/schema/visibility/profile.rb @@ -319,9 +319,9 @@ def possible_types_for(type) case type.kind.name when "INTERFACE" pts = [] - @schema.visibility.all_interface_type_memberships[type].each do |itm| - if @cached_visible[itm] && (ot = itm.object_type) && @cached_visible[ot] && referenced?(ot) - pts << ot + @schema.visibility.all_interface_type_memberships[type].each do |(itm, impl_type)| + if @cached_visible[itm] && @cached_visible[impl_type] && referenced?(impl_type) + pts << impl_type end end pts diff --git a/spec/graphql/schema/visibility_spec.rb b/spec/graphql/schema/visibility_spec.rb index 2aa1ada98f..9d4d2f3554 100644 --- a/spec/graphql/schema/visibility_spec.rb +++ b/spec/graphql/schema/visibility_spec.rb @@ -235,4 +235,40 @@ class OrphanType < GraphQL::Schema::Object assert_equal [], LazyLoadingSchema::OrphanType.all_field_definitions.first.extensions.map(&:class) end end + + describe "interfaces thru superclass" do + class InterfaceSuperclassSchema < GraphQL::Schema + module Node + include GraphQL::Schema::Interface + field :id, ID + end + + class NodeObject < GraphQL::Schema::Object + implements Node + end + + class Thing < NodeObject + field :name, String + end + + class Query < GraphQL::Schema::Object + field :node, Node + + def node + { id: "101", name: "Hat" } + end + + field :thing, Thing + end + + query(Query) + def self.resolve_type(...); Thing; end + use GraphQL::Schema::Visibility + end + end + + it "Can use interface relationship properly" do + res = InterfaceSuperclassSchema.execute("{ node { id ... on Thing { name } } }") + assert_equal "Hat", res["data"]["node"]["name"] + end end