Andre Zimpel
Andre Zimpel

Reputation: 2343

Reuse GraphQL arguments in Ruby

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

Answers (1)

Andre Zimpel
Andre Zimpel

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

Related Questions