如何在Ruby的GraphQL Union类型中使用列表?
在GraphQL Ruby中为Union类型添加列表成员的问题
背景
GraphQL Ruby文档中介绍了Union类型的定义方式:
class Types::CommentSubject < Types::BaseUnion description "Objects which may be commented on" possible_types Types::Post, Types::Image # 可选:定义此方法会覆盖`Schema.resolve_type` def self.resolve_type(object, context) if object.is_a?(BlogPost) Types::Post else Types::Image end end end
同时也说明了如何声明列表类型的字段:
# 返回列表类型的字段: # 等同于上方的`aliases: [String!]` field :aliases, [String] # 接受列表类型的参数: argument :categories, [Types::PostCategory], required: false
但找不到如何将列表作为Union的可选成员类型的实现方法。
尝试的代码及问题
我编写了如下Union类型定义:
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
这段代码能勉强运行,但当对象是数组时,返回的value字段会被序列化为字符串:
{ "name": "top_box", "type": "Array", "description": "The chosen values of the scale which should be combined", "position": 2, "optional": false, "value": "[\"8\", \"9\", \"10\"]" }
我期望的是直接返回字符串数组:
{ "name": "top_box", "type": "Array", "description": "The chosen values of the scale which should be combined", "position": 2, "optional": false, "value": [ "8", "9", "10" ] }
仅在一个关于“GraphQL Union嵌套Union”的回答评论中看到,这种需求可能无法实现。
尝试其他方法的错误信息
- 把
[GraphQL::Types::String]加入possible_types时,报错:
undefined method `graphql_name' for [GraphQL::Types::String]:Array
- 把
GraphQL::Schema::List.new(GraphQL::Types::String)加入possible_types时,报错:
undefined method `directives' for #<GraphQL::Schema::List:0x000000010f690950 @of_type=GraphQL::Types::String>
- 在
elsif object.is_a?(Array)分支里把[GraphQL::Types::String]替换为GraphQL::Schema::List.new(GraphQL::Types::String)时,报错:
.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>)`
现有解决方案(带嵌套)
我通过添加包装类实现了需求,但会多一层嵌套:
# frozen_string_literal: true module Types class ListOfStringsType < Types::BaseObject field :values, [String] end end
查询语句:
arguments { name type description position optional value { ... on ListOfStrings { values } } }
返回结果:
"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" } ]
我希望能避免这个额外的嵌套层级。
内容的提问来源于stack exchange,提问作者Beetle
相关产品推荐
相关产品推荐

