In the class-based API, is there a way to define field classes and hook them up to fields in your schema similar to how Mutation classes work?
This would help to reduce the clutter in my top-level Types::Query by externalizing field arguments and resolver functions to a separate file. There may be some other benefits as well (parity with mutations, reusing fields on different types, etc.)
Not yet, but that's a really interesting question!
To be honest, there's _room_ for some superclass of Mutation which is "just" a field, expressed as a class. In this way, it's something that takes the place of GraphQL::Mutation.
I'll think on it a bit and try something out, I wonder if anyone else has thought about it ...
That was my thinking as well. I mentioned it in Slack a couple days ago and it didn't garner much attention so I'm not sure how big of a need there is. Nevertheless, I think it would be a nice unification to have the option to write things like
# types/query.rb
field :comments, class: Queries::Comments
# types/mutation.rb
field :add_comment, class: Mutations::AddComment
# types/subscription.rb
field :comment_changed, class: Subscriptions::CommentChanged
Personally I think there is a need, GraphQL::Function is not quite right but we need the ability to split out code. I took a try in #1472; it's not quite there yet but it's a start.
I am also in favor of this. Being able to inherit from an ApplicationQuery would be super useful to allow us to remain writing conventional Ruby instead of the more pure-functional style.
Something like the following interface would feel really natural:
module Types
class Query < GraphQL::Schema::Object
field :search, query: Queries::Search
end
end
module Queries
class ApplicationQuery
def current_user
ctx[:current_user]
end
end
end
module Queries
class Search < ApplicationQuery
argument :search, Types::SearchInput
type Types::Search
def resolve(search)
if(current_user)
PrivateSearch.new(user: current_user, parameters: search)
else
PublicSearch.new(parameters: search)
end
end
end
end
@zspencer This is actually possible now in 1.8 as of https://github.com/rmosolgo/graphql-ruby/pull/1472. Your example would look like this:
module Types
class Query < GraphQL::Schema::Object
field :search, resolver: Queries::Search
end
end
module Queries
class ApplicationQuery < GraphQL::Schema::Resolver
def current_user
context[:current_user]
end
end
end
module Queries
class Search < ApplicationQuery
argument :search, Types::SearchInput
type Types::Search
def resolve(search)
if(current_user)
PrivateSearch.new(user: current_user, parameters: search)
else
PublicSearch.new(parameters: search)
end
end
end
end
Here is the diff: https://gist.github.com/mmun/aba5bb47dbc9a59ddda2a7702fc5bb50/revisions
Excellent! Thank you! I was reading through the docs and the examples and not finding anything like this, so I started going with the 'pass in a thing that responds to call' route and decided I didn't like it :).
Awesome! It took a while to find this thread though. @rmosolgo do you think this should be added to the docs?
Sure, feel free to add it!
I will try to do it this weekend!
Most helpful comment
I am also in favor of this. Being able to inherit from an ApplicationQuery would be super useful to allow us to remain writing conventional Ruby instead of the more pure-functional style.
Something like the following interface would feel really natural: