The GraphQL Ruby documentation shows how to define a union type:
class Types::CommentSubject < Types::BaseUnion description "Objects which may be commented on" possible_types Types::Post, Types::Image # Optional: if this method is defined, it will override `Schema.resolve_type` def self.resolve_type(object, context) if object.is_a?(BlogPost) Types::Post else Types::Image end end end and it shows how to declare that a field is a list outside of a union:
# A field returning a list type: # Equivalent to `aliases: [String!]` above field :aliases, [String] # An argument which accepts a list type: argument :categories, [Types::PostCategory], required: false but I can't for the life of me figure out how to use a list as a possible type that a union member could be.
My code looks something like this:
class Types::ArgumentValueType < Types::BaseUnion possible_types GraphQL::Types::String, GraphQL::Types::Boolean, GraphQL::Types::Int def self.resolve_type(object, _context) if object.is_a?(String) GraphQL::Types::String elsif object.is_a?(Array) [GraphQL::Types::String] elsif object.is_a?(FalseClass) GraphQL::Types::Boolean elsif object.is_a?(TrueClass) GraphQL::Types::Boolean elsif object.is_a?(Integer) GraphQL::Types::Int end end end … which sort of works, except that when it's an array, this value comes back as a string. In GraphiQL it looks like this (we're looking at the value field):
{ "name": "top_box", "type": "Array", "description": "The chosen values of the scale which should be combined", "position": 2, "optional": false, "value": "[\"8\", \"9\", \"10\"]" } We could potentially parse that in the client but ideally I'd like it to be an array of strings, like this:
{ "name": "top_box", "type": "Array", "description": "The chosen values of the scale which should be combined", "position": 2, "optional": false, "value": [ "8", "9", "10" ] }, But I can't see how to define that and the only information I could find anywhere is a brief comment in this answer to ‘GraphQL Union within Union’ which seems to suggest that it may not be possible.
Errors
If I try adding [GraphQL::Types::String] to possible_types, I get
undefined method `graphql_name' for [GraphQL::Types::String]:Array If I try adding GraphQL::Schema::List.new(GraphQL::Types::String) to possible_types, I get
undefined method `directives' for #<GraphQL::Schema::List:0x000000010f690950 @of_type=GraphQL::Types::String> and if I try replacing [GraphQL::Types::String] (under elsif object.is_a?(Array)) with GraphQL::Schema::List.new(GraphQL::Types::String), then I get
.resolve_type should return a type definition, but got #<GraphQL::Schema::List:0x000000010f9fd6b0 @of_type=GraphQL::Types::String> (GraphQL::Schema::List) from `resolve_type(Types::ArgumentValueType, [\"8\", \"9\", \"10\"], #<GraphQL::Query::Context:0x000000010f8ed018>)` Update
I managed to make an improvement by adding a wrapper class:
# frozen_string_literal: true module Types class ListOfStringsType < Types::BaseObject field :values, [String] end end Then, with a GraphQL query that looks a bit like this
arguments { name type description position optional value { ... on ListOfStrings { values } } } It produces output like this
"arguments": [ { "name": "top_box", "type": "Array", "description": "The chosen values of the scale which should be combined", "position": 2, "optional": false, "value": { "values": [ "8", "9", "10" ] } }, { "name": "measure", "type": "Measure", "description": "The name of the measure to be \"top-boxed\"", "position": 1, "optional": false, "value": "unique_and_different" } ] This is kind of okay, except that it has one extra level of indirection which I would prefer to avoid.