graphql-batch icon indicating copy to clipboard operation
graphql-batch copied to clipboard

Does not seem to work with unions

Open axos88 opened this issue 6 years ago • 3 comments

The resolve_type seems to get the promise rather than the solved value:

  Target = GraphQL::UnionType.define do
    name 'MyTarget'

    possible_types [X::Type, Y::Type]
    resolve_type ->(obj, _ctx) do
        binding.pry #                            -> obj.class == GraphQL::Batch::Promise
        case o
          when X then X::Type
          when Y then Y::Type
        end
      end
    end

  Type = GraphQL::ObjectType.define do
    name 'MyType'

    field :id, !GraphQL::Common::ObjectId

    field :targets, !types[!Target]  do
      resolve ->(obj, _args, _ctx) do
        case obj.target_type
          when 'X' then obj.targets.map { |t| RecordLoader.for(X).load(t) }
          when 'Y' then obj.targets.map { |t| RecordLoader.for(Y).load(t) }
        end
      end
    end

axos88 avatar Nov 16 '18 06:11 axos88

I tried to reproduce the issue with the following script

require 'graphql/batch'

class EchoLoader < GraphQL::Batch::Loader
  def perform(keys)
    keys.each { |key| fulfill(key, key) }
  end
end

class IntegerWrapperType < GraphQL::Schema::Object
  graphql_name "IntegerWrapper"

  field :num, Integer, null: false

  def num
    object
  end
end

class FloatWrapperType < GraphQL::Schema::Object
  graphql_name "FloatWrapper"

  field :num, Float, null: false

  def num
    object
  end
end

class NumberWrapperType < GraphQL::Schema::Union
  graphql_name "NumberWrapper"
  possible_types IntegerWrapperType, FloatWrapperType

  def self.resolve_type(object, context)
    case object
    when Integer
      IntegerWrapperType
    when Float
      FloatWrapperType
    else
      raise TypeError, "unexpected type #{object.class}"
    end
  end
end

class QueryType < GraphQL::Schema::Object
  graphql_name "Query"

  field :test, [NumberWrapperType], null: false

  def test
    [1, 2.0, 3].map { |num| EchoLoader.load(num) }
  end
end

class Schema < GraphQL::Schema
  query QueryType
  use GraphQL::Batch
end

query = '{
  test { ... on IntegerWrapper { num }, ... on FloatWrapper { num } }
}'

puts Schema.execute(query, variables: {}).to_h

but it works as expected and outputs

{"data"=>{"test"=>[{"num"=>1}, {"num"=>2.0}, {"num"=>3}]}}

Could you provide a complete script to reproduce the issue? Are you able to reproduce the issue with the latest version of the graphql gem?

dylanahsmith avatar Nov 19 '18 15:11 dylanahsmith

Hmm, i'll try to take a look at your code tomorrow probably.

axos88 avatar Nov 19 '18 17:11 axos88

If someone gets here by searching in Google I solved like this

In my Activity model, I have a polymorphic association called trackable.

module Types
  module Activities
    class ActivityType < Types::BaseModel
      field :action, String, null: false
      field :trackable, Types::Unions::TrackableUnion, null: false
      field :time_ago, String, null: false
      field :user, Types::Users::UserType
      field :organization, Types::Organizations::OrganizationType

      def user
        Loaders::RecordLoader.for(User).load(object.user_id)
      end

      def trackable
        case object.trackable_type
        when 'Question' then Loaders::RecordLoader.for(Question).load(object.trackable_id)
        when 'Video' then Loaders::RecordLoader.for(Question).load(object.trackable_id)
        when 'Course' then Loaders::RecordLoader.for(Course).load(object.trackable_id)
        end
      end
    end
  end
end
module Types
  module Unions
    class TrackableUnion < Types::BaseUnion
      description 'Activity trackable models'
      possible_types Types::Questions::QuestionType, Types::Videos::VideoType, Types::Courses::CourseType

      def self.resolve_type(object, _context)
        if object.is_a?(Question)
          Types::Questions::QuestionType
        elsif object.is_a?(Video)
          Types::Videos::VideoType
        elsif object.is_a?(Course)
          Types::Courses::CourseType
        end
      end
    end
  end
end

minardimedia avatar Sep 01 '22 21:09 minardimedia