Skip to content

Cannot use interface type for possible types of union types #3063

@leoc

Description

@leoc

I have recently updated graphql-ruby from 1.8.0 to 1.11.0 and since then this construction doesn't work anymore:

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'

  gem 'graphql', '1.11.0', require: true
  gem 'awesome_print'
end

Country = Struct.new(:id, :name)
Node = Struct.new(:id, :name, :path_id)
class Folder < Node; end

module Types; end

class Types::Country < GraphQL::Schema::Object
  description 'Resembles a Speaker Object Type'

  field :id, ID, null: false
  field :name, String, null: false
end

module Types::Node
  include GraphQL::Schema::Interface

  field :id, ID, null: false
  field :name, String, null: false
  field :path_id, String, null: false

  definition_methods do
    def resolve_type(object, _context)
      case object
      when ::Folder
        Types::Folder
      # ... more
      end
    end
  end
end

class Types::Folder < GraphQL::Schema::Object
  implements Types::Node
end

class Types::ScopableItem < GraphQL::Schema::Union
  possible_types(Types::Folder, Types::Country)

  def self.resolve_type(object, _context)
    case object
    when ::Folder then Types::Folder
    when ::Country then Types::Country
    end
  end
end

class QueryType < GraphQL::Schema::Object
  description "The query root of this schema"

  field :scopable_items, [Types::ScopableItem], null: false
  def scopable_items
    [
      ::Country.new(1, "Bizarro"),
      ::Folder.new(2, "Entry", "01.01.05 Entry")
    ]
  end
end

class AppSchema < GraphQL::Schema
  query QueryType
end

ap AppSchema.execute(<<QUERY).to_h
query {
  scopableItems {
    ... on Node {
      id
      label : pathId
    }
    ... on Country {
      id
      label : name
    }
  }
}
QUERY

When running it, I get:

{
    "errors" => [
        [0] {
               "message" => "Field 'label' has a field conflict: name or pathId?",
             "locations" => [
                [0] {
                      "line" => 5,
                    "column" => 7
                },
                [1] {
                      "line" => 9,
                    "column" => 7
                }
            ],
                  "path" => [],
            "extensions" => {
                     "code" => "fieldConflict",
                "fieldName" => "label",
                "conflicts" => "name or pathId"
            }
        }
    ]
}

I would have expected that I could use Node as a discriminator for this union type. I tried using possible_types(Types::Node, Types::Country), but it seems I am not allowed to specify interface types there. The only fix here is to copy the ... on Node part for all object types implementing Types::Node (e.g. ... on Folder, etc).

Maybe this is a bug, maybe this is intended behavior and I am doing something wrong. Either way I would love to discuss whether there are other possibilities <3

Also maybe this relates to #2426

In any case, thanks and cheers!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions