Is there a way to customize all fields with custom extras for use with an extension? The recommended way in the guide conflicts with anyone using the field class option such as field :node, field: GraphQL::Relay::Node.field.
It also seems that even if someone is using add_field(NodeField) theres no way to set its extras.
class FieldWithExtensionAndExtras < GraphQL::Schema::Field
def initialize(*args, **kwargs, &block)
kwargs = kwargs.merge(extensions: [MyExtension])
kwargs[:extras] ||= kwargs[:mutation]&.extras || []
kwargs[:extras] << :ast_node # 馃挘
super(*args, **kwargs, &block)
end
end
class BaseObject < GraphQL::Schema::Object
field_class FieldWithExtensionAndExtras
end
class Comment < BaseObject
implements GraphQL::Relay::Node.interface
description "A blog comment"
field :id, ID, null: false
field :body, String, null: false
end
class QueryRoot < BaseObject
# NOTE: The following field definition, using `field:` errors out with:
# `ArgumentError: keyword `extras:` may only be used with method-based resolve and class-based field such as
# mutation class, please remove `field:`, `function:` or `resolve:``
field :node, field: GraphQL::Relay::Node.field # 馃挜
field :comments, [Comment], null: false
end
class Schema < GraphQL::Schema
query QueryRoot
use GraphQL::Analysis::AST
end
Interesting! How about skipping the extras addition if kwargs[:field] is present? For example:
class FieldWithExtensionAndExtras < GraphQL::Schema::Field
def initialize(*args, **kwargs, &block)
kwargs = kwargs.merge(extensions: [MyExtension])
if !kwargs[:field]
kwargs[:extras] ||= kwargs[:mutation]&.extras || []
kwargs[:extras] << :ast_node # 馃挘
end
super(*args, **kwargs, &block)
end
end
That would at least side-step it in this case! For a more fine-grained approach, you could add another initialization option to skip the extras, and pass the option when adding Node.field. What do you think?
Ideally we should be able to customize every field without skipping any like the above case. Skipping the legacy Node.field case seems fine, but I don't think there's any way to customize a field added by add_field either unless we're missing something.
We can't override add_field on object types and set extras because GraphQL::Schema::Field doesn't expose it like it does with extensions. So I think one solution is to forget about the Node.field case and add an #extras method to set extras after the field is instantiated.
Is this more than an edge case? Why use add_field?
Isn't that the recommended solution to add the Node field now? It's used throughout the codebase when the new interpreter is used.
Oh, you're using it just for the Node field, I see. Somehow I got the impression that there was more to it than that.
add an
#extrasmethod to set extras after the field is instantiated
Yeah, that seems fine!
I'd like to have a go at making this change :)
One small issue so far:
add an #extras method to set extras after the field is instantiated.
GraphQL::Schema::Field already has:
# @return [Array<Symbol>]
attr_reader :extras
Any opinions on whether we prefer to leave that attr_reader alone and sprout a new method to add extras to an instantiated field (add_extras?), or do we prefer to make extras behave similar to extensions?
def extras(new_extras = nil)
if new_extras.nil?
# Read the value
@extras # returns [Array<Symbol>]
else
# ... @extras << ... etc.
similar to extensions
:+1:
Most helpful comment
Oh, you're using it just for the Node field, I see. Somehow I got the impression that there was more to it than that.
Yeah, that seems fine!