I'm trying to calculate a field's value of a Type, but I have to take in account the argument passed to my resolver by the user (query).
A dummy example:
Let's say I have two models in my rails app : Dog
and Price
(a Dog has_many
prices, depending on it's color). So I have a calculated field on DogType
: field :price, Float, null: true
where I take object.prices.minimum(:price)
, so far so good.
But when a user queries allDogs
with an argument color: black
(in order to have list with only black dogs), I do not want my calculated field price
to return the wrong price of all dogs, so I have to take in account that a filter was given in my resolver, and therefore filter the prices in the type as well.
My question is concerning graphql-ruby
but I'm interested in general about how to address such problems with GraphQL boilerplate : how to know properly in the object type, what filters were applied by the resolver ?
I followed this learn to do filtering so I have resolvers that look like this :
class Resolvers::DogsSearch < Resolvers::Base
# scope is starting point for search
scope { Dog.all }
type types[Types::DogType]
# inline input type definition for the advance filter
class DogFilter < ::Types::BaseInputObject
argument :color_id, ID, required: false
end
# when "filter" is passed "apply_filter" would be called to narrow the scope
option :filter, type: DogFilter, with: :apply_filter
def apply_filter(scope, value)
if value[:color_id]
# here's my take on how to do this : I store the filter in the context so I may access it later
context[:color_id] = value[:color_id]
self.scope = scope.where('color_id = ?', value[:color_id])
end
end
end
module Types
class DogType < Types::BaseObject
field :color_id, ID, null: false
...
field :price, Float, null: true
def price
# I have to retrieve filter from context if any
if context[:color_id]
Price.where(dog: object, color_id: context[:color_id]).minimum(:price)
else
object.prices.minimum(:price)
end
end
end
end
module Types
class QueryType < BaseObject
field :all_dogs, resolver: Resolvers::DogsSearch
end
end
This works but seems really inefficient, not Rail's way and definitely prone to errors. I have to do this in multiple places of my app, and fear that it won't scale well.
Is there any official way of handling this ?
I simplified the real example I'm facing for comprehension's sake but I think my core problem revolve in this.