Reputation: 2343
I'm building my first GraphQL api using rails and the graphql-ruby gem. So far it's been very simple and just awesome.
I'm kinda stuck now in regards to duplicate code. I've got a project management rails app which has spaces, todos (they belong to a space), users.
What I want to achieve is to be able to query spaces and its todos but also all the todos for the current user for example. For todos I want to be able to filter them using different arguments:
Done - Boolean, Scope - String (today or thisWeek), Assignee - Integer (Id of a user)
query {
space(id: 5) {
todos(done: false) {
name
done
dueAt
}
}
}
query {
me {
todos(done: false, scope: today) {
name
done
dueAt
}
}
}
That means everytime I got the field todos I want to be able to filter them whether they are done or due today etc.
I know how to use arguments and everything works fine but currently I got the same coder over and over again. How (and where) could I extract that code to make it reusable everytime I have the same todos field?
field :todos, [TodoType], null: true do
argument :done, Boolean, required: false
argument :scope, String, required: false
argument :limit, Integer, required: false
end
Upvotes: 4
Views: 1269
Reputation: 2343
Okay, as @jklina also said I ended up using a custom resolver.
I changed:
field :todos, [TodoType], null: true do
argument :done, Boolean, required: false
argument :scope, String, required: false
argument :limit, Integer, required: false
end
to:
field :todos, resolver: Resolvers::Todos, description: "All todos that belong to a given space"
and added a Resolver:
module Resolvers
class Todos < Resolvers::Base
type [Types::TodoType], null: false
TodoScopes = GraphQL::EnumType.define do
name "TodoScopes"
description "Group of available scopes for todos"
value "TODAY", "List all todos that are due to today", value: :today
value "THISWEEK", "List all todos that are due to the end of the week", value: :this_week
end
argument :done, Boolean, required: false
argument :scope, TodoScopes, required: false
argument :limit, Integer, required: false
argument :assignee_id, Integer, required: false
def resolve(done: nil, scope:nil, limit:5000, assignee_id: nil)
todos = object.todos
# filtering the records...
return todos.limit(limit)
end
end
end
Quite easy!
Upvotes: 1