Я пытаюсь вычислить значение поля типа Type, но я должен принять во внимание аргумент, переданный моему распознавателю пользователем (запрос).
Фиктивный пример:
Допустим, у меня в приложении есть две модели: Dog
и Price
(цена собаки has_many
, в зависимости от ее цвета). Итак, у меня есть вычисляемое поле на DogType
: field :price, Float, null: true
, где я беру object.prices.minimum(:price)
, пока все хорошо.
Но когда пользователь запрашивает allDogs
с аргументом color: black
(чтобы есть список только с черными собаками), я не хочу, чтобы мое вычисленное поле price
возвращало неправильную цену для всех собак, поэтому я должен принять во внимание, что в моем резольвере был задан фильтр, и поэтому фильтровать цены в типа также.
Мой вопрос касается graphql-ruby
, но меня интересует в целом то, как решать такие проблемы с образцом GraphQL: как правильно знать тип объекта, какие фильтры были применены преобразователем ?
Я следовал этому научиться делать фильтрацию , поэтому у меня есть резольверы, которые выглядят так:
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
Это работает, но кажется действительно неэффективным , а не путь Rail и определенно подвержен ошибкам. Я должен делать это в нескольких местах своего приложения и боюсь, что оно не будет хорошо масштабироваться.
Есть ли какой-нибудь официальный способ справиться с этим?
Я упростил реальный пример, которым я ' ради понимания, но я думаю, что моя основная проблема заключается в этом.