Skip to content

Commit

Permalink
Fix possible_type membership when inherited from superclass
Browse files Browse the repository at this point in the history
  • Loading branch information
rmosolgo committed Feb 13, 2025
1 parent 61816b0 commit b71f5f8
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
11 changes: 6 additions & 5 deletions lib/graphql/schema/visibility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions lib/graphql/schema/visibility/profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions spec/graphql/schema/visibility_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit b71f5f8

Please sign in to comment.