How to create function to return all common fields in absinthe

I’m trying to minimize repetitions in field definitions in a Type, input and query.
With this I don’t know how to do it, so I ask for help from the community.

Below is the code I’m trying to do, but without success.

defmodule MyApp.UserType do
  use Absinthe.Schema.Notation
  import Absinthe.Schema.Notation

  @descricao_type "User registration that can access the system."

  @desc @descricao_type
  object :user_types do
    MyApp.UserType.comuns_fields()

    field :password_hash,
          non_null(:string),
          description: "User-defined and already encrypted password."
  end

  # São todos os fields/campos que devem estar presentes no momento da inserção/atualização
  @desc @descricao_type
  input_object :user_input do
    MyApp.UserType.comuns_fields()

    field :password, non_null(:string),
      description: "Password entered by the user to be registered."
  end

  defmacro comuns_fields() do
    quote do
      field :email,
            non_null(:string),
            description: "Email address that will be used to log into the system."

      field :enable,
            :boolean,
            description: "Mark if user is active or not. By default it is active."
    end
  end
end

I’m getting the following error message:

== Compilation error in file lib/on_sistemas/schema/types/administracao/sistema/usuario_types.ex ==
** (CompileError) lib/my_app/types/user_types.ex:16: undefined function comuns_fields/0 (there is no such import)
    (absinthe 1.7.0) expanding macro: Absinthe.Schema.Notation.input_object/2
    lib/my_app/types/user_types.ex:16: OnSistemas.Graphql.Schema.Types.Administracao.Sistema.UsuarioType (module)

Hello and welcome,

You should not use the macro inside the module it is defined in. It is not yet available when You call it :slight_smile:

The easiest way is to use another module for the macro.

There is a hard way I think… like using @after_compile

Absinthe has a built-in method to reuse fields.

  object :user_fields do
      field :email,
            non_null(:string),
            description: "Email address that will be used to log into the system."

      field :enable,
            :boolean,
            description: "Mark if user is active or not. By default it is active."
  end

  input_object :user_input do
    field :password, non_null(:string),
      description: "Password entered by the user to be registered."

    import_fields :user_fields
  end
2 Likes

Thank you all so much for your attention and feedback.

As absinthe already offers a solution to avoid repetitions, I will adopt the same pattern.
What is the suggestion of @maartenvanvliet in post.

Thank you.