Absinthe: how to get parent field arguments

Hi, I am trying to add custom type to relay connection and inside resolve I need to get parent’s arguments (values). Is there a way how to do that?

Imagine you have:

orders(first: 10, orderNumberPrefix: "ORDER 1") {
    totalCount
}

I need to get orderNumberPrefix argument value while resolving totalCount.

Thank you.

2 Likes

In your case, the second arguments of the resolver function called from schema would be %{first: 10, order_number_prefix: "ORDER 1"}.

When resolving orders, then yes. But if you try to resolve totalCount, then args parameter is %{}.

I’ve got what you want to do. You want to get the args in the resolver function for totalCount, is it right?

orders(first: 10, orderNumberPrefix: "ORDER 1") {
  totalCount {
    id
  }
}

In such case, I’d build and set the data in the top most resolver(for orders), even for totalCount. I don’t use any resolver for totalCount.

Did you ever figure this out? Trying to do something similar

I hope this helps someone. I lost a bit of time on this problem and I’m not sure if there’s a better way but to access the root arguments from a nested resolver you can do the following:
1- create a custom middleware that accesses the arguments and stores them into the context
2 - register the middleware
3 - access parent arguments via context

In detail

1 - Custom middleware that’ll store the parent/root arguments into the context

defmodule MyAppWeb.GraphQL.Middleware.RootArguments do
  @behaviour Absinthe.Middleware
  @impl Absinthe.Middleware
  def call(resolution, _config) do
    %{ resolution | context: Map.put(resolution.context, :root_arguments, resolution.arguments || %{})}
  end
end

2 - Register it to the GraphQL Schema

defmodule MyAppWeb.GraphQL.Schema do
  use Absinthe.Schema
  import_types MyAppWeb.GraphQL.Types
  # ...
  alias MyAppWeb.GraphQL.Middleware.RootArguments

  def middleware(middleware, _field, %{identifier: type}) when type in [:query, :mutation] do
    SafeResolution.apply(middleware) ++ [RootArguments]
  end

  def middleware(middleware, _field, _object) do
    middleware
  end
end

3 - And then inside of resolvers you can access the arguments via context:

object :orders do
  field :total_count, :integer do
    resolve(fn _parent, _args, info ->
      arguments = Map.get(info.context, :root_arguments, %{})
      {:ok, count} = MyApp.Orders.count(arguments)
      {:ok, count}
    end)
  end
end

If there’s a better way please let me know :slight_smile:

3 Likes