Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix possible_type membership when inherited from superclass #5236

Merged
merged 1 commit into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading