Absinthe: accessing parent relationships

This may not be possible, but I’m looking to do something like this:

# query
albums {
  mediaCollection {
    images {
      ...
    }
  }
}

# schema
object :image do
  field :id, non_null(:id)
  field :preview_src, :string
  field :src, :string do
    resolve fn(image, args, resolution) ->
      if (image.mediaCollection.album.owner_id == resolution.context.current_user.id) do
        {:ok, image.src}
      end
    end
  end
end

The tricky bit being image.mediaCollection.album.owner_id, in which none of the parent relationships are loaded. (And preloading them at this level would lead to an N+1 problem.) I’ve rooted around in the resolution object, and it looks like the context has a reference to the parent relationships, but they aren’t yet resolved, so I can’t access them or, more specifically, the album’s owner_id.

Is there a way to access parent relationships? Have they even been fetched from the db yet, or is absinthe somehow fetching records from the bottom up?

Thank you! This is my first question here.

This may help:

  1. Resolvers run top down and possibly in parallel as siblings (not sure about the parallel part).
  2. the parent arg to this child resolver can contain anything the higher level resolver wants to put there. I’ve used this to pass the full result of an ecto query in a key that is not in the gql schema to allow child resolvers use preloaded structs. This does mean an implicit or pattern matched agreement is part of the child resolver.

I don’t know if this is a sanctioned method, frankly. But, a delivered gql result will maximally contain what the schema allows.

Hi! I’ve been trying to figure out how to do this, but w/ no luck. Could you give an example of how a higher level resolver can modify the parent arg of a child resolver? In particular, when using dataloader? When I look at the result of a dataloader resolver, there’s actually no sign of the children:

    field :image, :image do
      resolve(fn (parent, args, resolution) ->
        result = dataloader(:media).(parent, args, resolution)
        IO.inspect(result)
        result
      end)
    end

But maybe I’m approaching this the wrong way?

1 Like