rmosolgo / graphql-ruby

Ruby implementation of GraphQL
http://graphql-ruby.org
MIT License
5.36k stars 1.37k forks source link

GraphQL::Relay::GlobalIdResolve forward compatibility #3826

Closed ivanbrennan closed 2 years ago

ivanbrennan commented 2 years ago

I have a few pieces of code that manually call .id_from_object to calculate a Relay-style node ID, so they need to determine the appropriate type to pass into the call,

def self.id_from_object(obj, type, ctx)

to ensure they're consistent with the behavior of GraphQL::Relay::GlobalIdResolve.

Due to the way Relay node IDs are currently calculated,

# lib/graphql/relay/global_id_resolve.rb
type = @type.respond_to?(:graphql_definition) ? @type.graphql_definition(silence_deprecation_warning: true) : @type
ctx.query.schema.id_from_object(obj, type, ctx)

my code does the following:

type = schema.resolve_type(GraphQL::Types::Relay::Node, obj, ctx)

# https://github.com/rmosolgo/graphql-ruby/pull/3750
type = type.respond_to?(:graphql_definition) ? type.graphql_definition(silence_deprecation_warning: true) : type

schema.id_from_object(obj, type, ctx)

My assumption is that when .graphql_definition objects are removed (in GraphQL-Ruby 2.0), the code in GraphQL::Relay::GlobalIdResolve will start passing the class that describes the type, rather than passing an instance of GraphQL::ObjectType. Is that the case?

For example, say obj is an instance of an ActiveRecord model Song, @type is the class Types::SongType, and @type.graphql_definition is an instance of GraphQL::ObjectType displayed as Song. Once .graphql_definition objects are removed, can I expect .id_from_object to receive Types::SongType (the class itself, not an instance of it) as it's second argument (type)?

rmosolgo commented 2 years ago

Hi, great question. Yes, in GraphQL-Ruby 2.0, all types will be classes -- GraphQL::ObjectType will be completely removed.

Likewise, GraphQL::Relay::GlobalIdResolve will also be removed; instead, global_id_field will call .id_from_object directly. Here's the implementation that's currently only the 2.0-dev branch:

https://github.com/rmosolgo/graphql-ruby/blob/23386d7c3c71d5995e92befd560450df0e7b370e/lib/graphql/schema/member/has_fields.rb#L105-L111

I hope that helps -- let me know if there's anything else I can help with while you consider that migration!

ivanbrennan commented 2 years ago

I hope that helps -- let me know if there's anything else I can help with while you consider that migration!

@rmosolgo That's very helpful, thanks for clarifying :+1:

I had one followup question: will it still be possible to call .graphql_name on a type class (e.g. Types::SongType.graphql_name) to determine its name in the client-facing schema? But since you mentioned the 2.0-dev branch (which I wasn't previously aware of), I took a look at that and it looks like .graphql_name is still available, so I guess that answers my question :)

Thanks again for all your work!

rmosolgo commented 2 years ago

.graphql_name on a type class

Yep! (In fact, .graphql_name was added specifically for classes: since .name returns the Ruby class name, I needed some other method for the GraphQL type name.)