Closed woahstorkdork closed 6 years ago
Hi,
This is a bit tricky. I would suggest todo something like the following:
module Resolvers
class PostSearch < Resolvers::BaseSearchResolver
# you are correct to have a special type for grouping the result
type do
name 'PaginatedPosts'
field :posts, !types[!Types::PostType], property: :results
field :postsCount, !types.Int, property: :count
field :pagesCount, !types.Int, property: :pages_count
end
# overwrite this, so instead of results, it returns SearchObject
def self.call(object, args, context)
new(filters: args.to_h, object: object, context: context)
end
# you can define custom methods here
def pages_count
# ... calculate pages
end
# Rest of the code from:
# https://github.com/RStankov/SearchObjectGraphQL/blob/master/example/app/graphql/resolvers/post_search.rb
end
end
I hope this helps đŸ™Œ
I'll give it a shot. Thank you so much !
You are welcome :)
For anyone that may be interested in a way to solve pagination, I ended up implementing a Resolvers::ListResolverBase
that all of the SearchObjects inherit from.
Here is the ListResolverBase:
require 'search_object/plugin/graphql'
class Resolvers::ListResolverBase
include SearchObject.module(:graphql)
include SearchObject.module(:kaminari)
option( :paginate, type: Types::PaginationInput, with: :pagination, default: {page: 1, per: 10} )
def self.call(object, args, context)
search_object = new( filters: args.to_h, object: object, context: context)
results, paginate = search_object.results, args["paginate"]
return self.paginate_results(results, paginate)
end
private
def self.paginate_results(results, paginate)
records = results.page(paginate["page"])
.per(paginate["per"])
OpenStruct.new(
data: records,
recordsCount: records.total_count,
pagesCount: records.total_pages,
currentPage: records.current_page
)
end
def pagination(scope, value)
end
end
and I simply define a custom type in the respective resolver inhering from this class:
type do
name 'PaginatedProducts'
field :data, !types[!Types::ProductType]
field :recordsCount, types.Int
field :pagesCount, types.Int
field :currentPage, types.Int
end
voila, all SearchObjects inheriting from Resolvers::ListResolverBase
and with a defined custom type now have pagination !
Thanks for your help in solving this @RStankov !
PS. Side question. I felt it was a little hacky adding an empty paginate option/method in order to whitelist those params. I tried adding an argument argument :paginate, type: Types::PaginationInput
but it threw an error.
Is there a way to define an argument in SearchObject without a corresponding option method?
So fundamentally my main question is:
My use case for this is pagination, hence the pagination-flavored question. I'd also welcome any other alternatives/suggestions for achieving the end behavior.
Currently Implemented: I set up an option within the search object resolver for pagination...
option( :paginate, type: Types::PaginationInput, with: :pagination, default: { first: 10, skip: 0} )
and I have simple limit offset method to handle this...Note: I'm currrently returning a list of Products
type !types[Types::ProductType]
The Problem The only problem with that is that through this implementation the client doesn't know what is the total number of records and so it makes it difficult to create any meaningful pagination ui/controls.
Ideally, I'd like to return a records count and a pages account as well. I noticed that your base SearchObject has a kaminari plugin and that it seems to also work with the graphql plugin. I mention this because I'd like to use kaminari's helpers to achieve this functionality.
The Ideal solution or so I think I'd like to create a custom type to return a paginated list of Products, along with the pagination metadata. Something along the lines of
And to achieve this, I think it'd be ideal to set up some kind of after_resolve callback that gets called at the end of processing
scope
through all of the SearchObject's options to create/return an OpenStruct following the custom type's format:Any and all help with this would be GREATLY appreciated!!!! It'll continue trying different things in the mean time.
Thank you so much for your awesome work @RStankov !