Absinthe. How to set default values for enum in input type?

Hello, I wanted to create an input object with an enum type and a default value but I can’t make it work.

My query

query GetStatuses {
  statuses {
    text
    recipient {
      nickname 
    nickname
    }
    sender {
      nickname
    }
  }
}

And my resolver function head

def list_statuses(_, %{input: filters}, %{context: %{current_user: current_user}})

I am trying to start simple with one filter and add more filters later

  • First attempt


# the types module 
 input_object :statuses_privacy do
    field :privacy, :privacy
  end

  enum :privacy do
    value :public
    value :private
  end

# in the query object
  field :statuses, list_of(:status) do
     arg :input, :statuses_privacy, default_value:  :public
     resolve &Statuses.list_statuses/3
   end

This gives

Request: POST /graphql/graphiql
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol Enumerable not implemented for :public of type Atom. This protocol is implemented for the following type(s): Ecto.Adapters.SQL.Stream, Postgrex.Stream, DBConnection.Stream, DBConnection.PrepareStream, HashSet, Date.Range, MapSet, IO.Stream, Map, Function, List, HashDict, Stream, GenEvent.Stream, Range, File.Stream
  • Second attempt

# in the query object
    field :statuses, list_of(:status) do
      arg :input, :statuses_privacy, default_value:  %{privacy: :public}
      resolve &Statuses.list_statuses/3
    end

This works for a query but when graphiql tries to fetch the schema I get again

Request: POST /graphql/graphiql
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol String.Chars not implemented for %{privacy: :public} of type Map. This protocol is implemented for the following type(s): Postgrex.Query, Postgrex.Copy, Decimal, Float, Date, Integer, Version.Requirement, Time, DateTime, List, BitString, NaiveDateTime, URI, Version, Atom
        (elixir 1.10.3) lib/string/chars.ex:3: String.Chars.impl_for!/1
        (elixir 1.10.3) lib/string/chars.ex:22: String.Chars.to_string/1
        (absinthe 1.4.16) lib/absinthe/type/built_ins/introspection.ex:288: anonymous fn/2 in Absinthe.Type.BuiltIns.Introspection.__absinthe_type__/1
        (absinthe 1.4.16) lib/absinthe/resolution.ex:206: Absinthe.Resolution.call/2
  • Third attempt


# in the types module
  input_object :statuses_privacy do
    field :privacy, :privacy, default_value: :public
  end

  enum :privacy do
    value :public
    value :private
  end

# in the query object
    field :statuses, list_of(:status) do
      arg :input, :statuses_privacy
      resolve &Statuses.list_statuses/3
    end

This time the input map is not passed at all in the resolver

** (exit) an exception was raised:
    ** (FunctionClauseError) no function clause matching in TweetCloneWeb.Resolvers.Statuses.list_statuses/3
        (tweetclone 0.1.0) lib/tweetclone_web/resolvers/statuses.ex:16: TweetCloneWeb.Resolvers.Statuses.list_statuses(%{}, %{}, #Absinthe.Resolution<[acc: %{Absinthe.Middleware.Async => false, Absinthe.Middleware.Batch => %{input: [], output: %{}}}, adapter: Absinthe.Adapter.LanguageConventions, arguments: %{}, context: %{__absinthe_plug

How can I have an input argument as a map with default values like this:

%{input: {privacy: :public}}

and default value set to :public?

I was able to provide a default with (using examples from the docs here)

  enum :contact_type do
    value(:phone, as: "phone")
    value(:email, as: "email")
  end
input_object :contact_input do
  field :type, non_null(:contact_type), default_value: "phone"
  field :value, non_null(:string)
 end
1 Like