Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not seem to work with unions #91

Closed
axos88 opened this issue Nov 16, 2018 · 4 comments
Closed

Does not seem to work with unions #91

axos88 opened this issue Nov 16, 2018 · 4 comments

Comments

@axos88
Copy link

axos88 commented Nov 16, 2018

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
@dylanahsmith
Copy link
Contributor

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?

@axos88
Copy link
Author

axos88 commented Nov 19, 2018

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

@minardimedia
Copy link

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

@gmac
Copy link
Contributor

gmac commented May 22, 2024

Closing this out as the issue is from 2018 using a different major version of GraphQL. GraphQL::Batch is agnostic about schema the type system, it's simply a lazy resolver hook. Post-loading, you must cast the loaded records appropriately through GraphQL Ruby methodologies, as demonstrated by @minardimedia.

@gmac gmac closed this as completed May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants