Generate dynamic objects with Absinthe

Hello everyone, I’m looking to generate objects, queries , and mutations dynamically. The problem is that we can have many macros inside of other macros
For example, I want to generate the following object:

object :comment do
    field(:id, :id)
    field(:body, :string)
    field(:author_id, :id)
    field(:author, :author, resolve: assoc(:author)) do
      complexity(fn _, child_complexity ->
        child_complexity + 1000
      end)
      arg(:filter, :filters_avatar)
      resolve(&AuthorResolver.all/3)
    end
  end

I’ve tried to use basic notations as:

def object_wrapper(identifier, fields) do
    object =
      quote do
        object unquote(identifier) do
          for {name, data_type} <- fields do
            field(unquote(name), unquote(data_type))
          end
        end
      end
    Code.eval_quoted(object, [identifier: identifier, fields: fields], __ENV__)
  end

Do you have any recommendations on which approach should I take?

The Absinthe DSL is not sufficiently set up to allow this due to how it does its macro internals. Ecto, by contrast, works perfectly fine doing this. I began refactoring the DSL internals to be friendlier to this style of metaprogramming but I lost motivation.

3 Likes

Absinthe 1.5 which is currently at version v1.5.0-alpha.0 has a substantial re-write of the DSL to create a schema with the explicit goal of making it easier to generate a schema programmatically. So if you look at that branch you may have an easier time. Although I’m not sure of any good guides to the internals, but a good starting point might be the SDL implementation.

3 Likes