изменить значение поля типа в зависимости от аргумента решателя в graphql- ruby - PullRequest
1 голос
/ 27 марта 2020

Я пытаюсь вычислить значение поля типа 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 и определенно подвержен ошибкам. Я должен делать это в нескольких местах своего приложения и боюсь, что оно не будет хорошо масштабироваться.

Есть ли какой-нибудь официальный способ справиться с этим?

Я упростил реальный пример, которым я ' ради понимания, но я думаю, что моя основная проблема заключается в этом.

...