Using 1.8.4....
Two Connection classes:
# frozen_string_literal: true
# Define Graphql Connection for Roles
class RBAC::Connections::RolesConnection < ::Types::BaseConnection
graphql_name 'RolesConnection'
edge_type(RBAC::Edges::RolesEdge, node_type: RBAC::Types::RoleType)
end
# frozen_string_literal: true
# Define Graphql Connection for user to Roles
class RBAC::Connections::UserRolesConnection < ::Types::BaseConnection
graphql_name 'UserRolesConnection'
edge_type(RBAC::Edges::UserRolesEdge)
md5-1e64f120e46a5a44521bae3f65b0e58b
```ruby
# frozen_string_literal: true
# User => UsersRoles => Role
class RBAC::Edges::UserRolesEdge < ::Types::BaseEdge
graphql_name 'UserRolesEdge'
node_type(RBAC::Types::RoleType)
field :added_on, String, 'The date that this User was added to this Role', null: true
def added_on
user = object.parent
role = object.node
# lets create a custom attribute for how long this relationship has been here
# we will query from the UsersRole Join Table
added_on = UsersRole.where(user: user, role: role).first
added_on&.created_at
end
end
md5-f24d4bfd4a34cffd3fd058208a3897d9
I, [2018-07-05T15:14:58.365193 #44737] INFO -- : Completed 500 Internal Server Error in 345ms (ActiveRecord: 13.8ms)
F, [2018-07-05T15:14:58.365746 #44737] FATAL -- :
F, [2018-07-05T15:14:58.365771 #44737] FATAL -- : RuntimeError (Duplicate type definition found for name 'RoleEdge' at 'Field RolesConnection.edges's return type' (RBAC::Edges::UserRolesEdge, RBAC::Edges::RolesEdge)):
F, [2018-07-05T15:14:58.365786 #44737] FATAL -- :
F, [2018-07-05T15:14:58.365800 #44737] FATAL -- : app/controllers/rbac_graphql_controller.rb:18:in `query'
It seems that the template graphql-ruby/lib/graphql/types/relay/base_edge.rb class tries to automatically apply a graphql_name to the object edge returned by the "edges" field based on the class name of the node_type.
If you have implemented two different edges, that return the same node_type, then the namespace conflicts.
Looking at your BaseEdge Class, it seems that setting "graphql_name" on line 35 is both redundant (since it's already set in the Edge class implementation), and causing this particular problem.
I commented it out completely and it solved this naming collision.
def node_type(node_type = nil)
if node_type
@node_type = node_type
wrapped_type_name = node_type.graphql_name
# Set this to be named like the node type, but suffixed with `Edge`
# graphql_name("#{wrapped_type_name}Edge")
# Add a default `node` field
field :node, node_type, null: true, description: 'The item at the end of the edge.'
end
@node_type
end
Maybe that graphql_edge(...) call should be refactored to a ||=. Thanks for sharing your solution!
Hi @rmosolgo! May I ask why this issue was closed? It's still in master, causing the exact issue @clader described.
I don't have the capacity to prioritize the fix, and a solution was found by the reporter, so I didn't have any concrete next steps. Feel free to open a PR to address this case if you'd like!
@clader @rmosolgo Running into this as well - looks like we can't define two edges that use the same node_type. Does the monkey patching fix above have any known side effects?
I think the only side effect would be that if you don't give your custom edge a name, this patch will not let it fall back to a "default" name, and hence throw an error.
Got it. Just for my sanity - having different edges that have the same node_type is a valid (and common?) way to do graphql, right? How else do you add different sets of data to edges of the same node type? E.g. a model with lots of has_many :through relationships that have data in the through table.
I can鈥檛 say how common this is , but what you describe was my exact use case, and why I needed to do this.
I found another temporay work around without monkey patching. Just add the #graphql_name call _after_ the #node_type method.
Example:
class ArticleReadlistEdgeType < GraphQL::Types::Relay::BaseEdge
node_type(ArticleType)
graphql_name('ArticleReadlistEdge')
...
This overrides the name after it's set in #node_type and resolves the duplicate.
I would love the see this fixed or documented. Having multple edges to one node type seems a fairly common use-case to me.
Most helpful comment
I found another temporay work around without monkey patching. Just add the #graphql_name call _after_ the #node_type method.
Example:
This overrides the name after it's set in #node_type and resolves the duplicate.
I would love the see this fixed or documented. Having multple edges to one node type seems a fairly common use-case to me.