graphql-elixir / graphql

GraphQL Elixir
Other
859 stars 47 forks source link

Union help #110

Closed bringking closed 7 years ago

bringking commented 7 years ago

Thanks for the awesome library, I am loving creating a GraphQL service in Elixir. I am running into an issue I hope you can shed some light on. I have a field on a value that is a string "type". This field is a string from the backing API, but I want expose it as a Union Type. I setup the "Banner" type as shown -

def type do
    %ObjectType{
      name: "Banner",
      description: "A Banner in the system",
      fields: %{
        id:
          %{type: %ID{}, description: "The ID of the banner"},
        avatar_image:
          %{type: Image, description: "The avatar image for the banner"},
        desktop_banner_image:
          %{type: Image, description: "The desktop image for the Banner (wide)"},
        mobile_banner_image:
          %{type: Image, description: "The avatar image for the Banner (square)"},
        type:
          %{
            type: banner_types,
            description: "The type for this banner",
            resolve: fn
              banner, params, ast -> Api.get_by_id(get_in(banner,["slug"]))
            end
          }
      }
    }
  end

and the "banner_types" union type as follows -

  def banner_types do
    GraphQL.Type.Union.new %{
      name: "BannerTypes",
      types: [Product],
      resolver: fn
        (product) -> Product
      end
    }
  end

I can see the initial resolver in the Banner make the API call, then pass the result to the the Union resolver, which resolves the Type Product. This correctly resolves the __typename in the query, but it fails on any fragments for Product

     ... on Product {
        id
      }

I get something like -

** (exit) an exception was raised:
    ** (KeyError) key :name not found in: %{..} # rest of Struct omitted

Any idea how to make this work with fragments? Thank you again!

bringking commented 7 years ago

Derp, I was passing the Module and not the "type". I fixed this by just changing ->

 def banner_types do
    GraphQL.Type.Union.new %{
      name: "BannerTypes",
      types: [Product],
      resolver: fn
        (product) -> Product
      end
    }
  end

to

 def banner_types do
    GraphQL.Type.Union.new %{
      name: "BannerTypes",
      types: [Product.type],
      resolver: fn
        (product) -> Product.type
      end
    }
  end