Hey Alchemists,
I am attempting to pass in a list of maps into a macro so that it can be used to generate an absinthe object
for my schema. I have tried several approaches to inject the fields into the macro: var!
, Macro.expand
, Macro.escape
but I still haven’t untangled this problem. I would have expected the expansion to allow me to use the fields in the unquote block. Below is my spike macro and it’s invocation. What am I failing to understand?
defmodule Foo do
defmacro do_it(fields) do
quote do
object :item do
unquote do
fields
|> Enum.map(fn f ->
name = f |> Map.get(:field)
type = f |> Map.get(:type)
quote do: field(unquote(name), unquote(type))
end)
end
end
end
end
def fields do
[
%{field: :warble, type: :id},
%{field: :wazzle, type: :string},
%{field: :tex, type: :integer}
]
end
end
# Invocation
require Foo
Foo.do_it(Foo.fields())
# Compile error Error
== Compilation error in file lib/wibble_web/schema.ex ==
** (Protocol.UndefinedError) protocol Enumerable not implemented for {{:., [line: 29], [{:__aliases__, [line: 29], [:Foo]}, :fields]}, [line: 29], []}
(elixir) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir) lib/enum.ex:141: Enumerable.reduce/3
(elixir) lib/enum.ex:3015: Enum.map/2
expanding macro: Foo.do_it/1
lib/wibble_web/schema.ex:29: WibbleWeb.Schema (module)
(elixir) lib/kernel/parallel_compiler.ex:208: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6