SearchObjectGraphQL icon indicating copy to clipboard operation
SearchObjectGraphQL copied to clipboard

Using filter as object argument

Open rikusen0335 opened this issue 3 years ago • 1 comments

Hello, I'm really new to Ruby and Rails and also GraphQL. I know and sorry that I am asking stupid question, but please tell me if I wonder I can do like:

query {
  posts(filter: {
    category: "GraphQL",
    title: "Coonection Type"
  }) {
    nodes {
      id
      title
    }
  }
}

The point is here

  posts(filter: {
    category: "GraphQL",
    title: "Coonection Type"
  }) {

As a default the filter params are used like this, but it is pain to use filters in frontend if we had a lot of filters

  posts(
    category: "GraphQL",
    title: "Coonection Type",
    before: "..." # also like if using connection_type
  ) {

I am ending up with regular expression using option, but I couldn't know how can I do it.

rikusen0335 avatar Sep 23 '21 01:09 rikusen0335

Hi @rikusen0335 👋

I think you want to make an "Input Object". That way you could use the filter: argument the way you want, in your query.

Modifying the example PostSearch resolver in this repository:

# frozen_string_literal: true

module Resolvers
  class PostSearch < Resolvers::BaseSearchResolver
    type Types::PostType.connection_type, null: false
    description 'Lists posts'

    class OrderEnum < Types::BaseEnum
      graphql_name 'PostOrder'

      value 'RECENT'
      value 'VIEWS'
      value 'LIKES'
      value 'COMMENTS'
    end

    scope { object.respond_to?(:posts) ? object.posts : Post.all }

    # you could also put this InputObject in a separate file, if you prefer 
    class PostFilters < Types::BaseInputObject
      argument :id, type: types.String, requred: false
      argument :title, type: types.String, requred: false
      argument :body, type: types.String, requred: false
      argument :categoryId, type: types.String, requred: false
      argument :categoryName, type: types.String, requred: false
      argument :published, type: types.Boolean, requred: false
      argument :order, type: OrderEnum, default: 'RECENT', requred: false
    end

    option :filter, type: PostFilters, with: :apply_filters

    def apply_filters(scope, value)
      scope = scope.where(id: value[:id]) if value[:id]
      scope = scope.where("title LIKE ?", escape_search_term(value[:title])) if value[:title]
      scope = scope.where("body LIKE ?", escape_search_term(value[:body])) if value[:body]
      scope = scope.where(category_id: value[:category_id]) if value[:category_id]
      if value[:category_name]
        scope = scope.joins(:category).where 'categories.name LIKE ?', escape_search_term(value[: category_name])
      end
      ...
    end

then

query postsFiltered {
  posts(filter:{
    title:"Armillaria"
    body:"oak forest"
  }) {
    pageInfo {
      startCursor
      endCursor
      hasNextPage
      hasPreviousPage
    }
    edges {
      cursor
      node {
        id
        textName
        where
        notes
      }
    }
  }
}

nimmolo avatar Nov 01 '21 01:11 nimmolo