Describe the bug
As the title says, the Relay node fields are not added to the query type.
Versions
graphql version: 1.10.7
rails (or other framework): 6.0.2.2
GraphQL query
query {
node(id: "Q2Fwc3VsZS0z") {
... on Node {
id
}
}
}
{
"errors": [
{
"message": "Field 'node' doesn't exist on type 'Query'",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"query",
"node"
],
"extensions": {
"code": "undefinedField",
"typeName": "Query",
"fieldName": "node"
}
}
]
}
Steps to reproduce
Add the following fields to your query_type.rb
# Implement the relay spec
add_field GraphQL::Types::Relay::NodeField
add_field GraphQL::Types::Relay::NodesField
Expected behavior
The node and nodes fields should be added to the schema.
Actual behavior
They're not added to the schema.
Additional context
This issue can be solved by downgrading to Graphql-ruby version 1.10.5 opposed to the original version
I bet the problem is about orphan_types: if there are no registered implementations of the Node interface, then those fields will be hidden from the schema because their return type is invalid.
Here's a working example:
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'graphql', "1.10.7"
end
class Thing < GraphQL::Schema::Object
implements GraphQL::Types::Relay::Node
end
class Query < GraphQL::Schema::Object
add_field GraphQL::Types::Relay::NodeField
add_field GraphQL::Types::Relay::NodesField
end
class Schema < GraphQL::Schema
query(Query)
def self.resolve_type(*)
Thing
end
def self.object_from_id(id, ctx)
{ id: id }
end
orphan_types(Thing)
end
pp Schema.execute <<~GRAPHQL
{
node(id: "abcd") {
...on Thing {
id
}
}
nodes(ids: ["abcd"]) {
...on Thing {
id
}
}
}
GRAPHQL
# => #<GraphQL::Query::Result @query=... @to_h={"data"=>{"node"=>{"id"=>"abcd"}, "nodes"=>[{"id"=>"abcd"}]}}>
To make sure that Node (and its implementations) are properly registered in the schema:
orphan_types (as shown above)(The problem is, GraphQL-Ruby can only find object times that are linked to the schema in some way; orphan_types is there to add types that aren't otherwise referenced.)
Let me know if that doesn't fix it for you!
Hey, adding in the orphan_types manually seems to work but if you have 100s of types It could get a bit messy, is there a more elegant solution?
I had it working without the orphan type
Hey, adding in the orphan_types manually seems to work but if you have 100s of types It could get a bit messy, is there a more elegant solution?
If you have a predictable way of naming the graphql_name from the model name then you can dynamically evaluate it.
example: User =>Types::UserType, Article => Types::ArticleType
def self.resolve_type(type, obj, ctx)
klass = obj.class
gql_type = "Types::#{klass}Type"
# if you have inheritance in models & type
# unless const_defined? gql_type
# gql_type = "Types::#{klass.superclass}Type"
# end
gql_type.constantize
end
Most helpful comment
I bet the problem is about
orphan_types: if there are no registered implementations of theNodeinterface, then those fields will be hidden from the schema because their return type is invalid.Here's a working example:
To make sure that
Node(and its implementations) are properly registered in the schema:orphan_types(as shown above)(The problem is, GraphQL-Ruby can only find object times that are linked to the schema in some way;
orphan_typesis there to add types that aren't otherwise referenced.)Let me know if that doesn't fix it for you!