Compile Time values can not be provided for enum.
use Absinthe.Schema.Notation
variable = [:foo, :bar]
enum :enum_variable, values: variable
@attribute [:foo, :bar]
enum :enum_attribute, values: @attribute
== Compilation error in file lib/art_email/schema/content_types.ex ==
** (FunctionClauseError) no function clause matching in Absinthe.Type.Enum.Value.build/1
The following arguments were given to Absinthe.Type.Enum.Value.build/1:
# 1
{:templates, [line: 8], nil}
Attempted function clauses (showing 1 out of 1):
def build(raw_values) when is_list(raw_values)
lib/absinthe/type/enum/value.ex:31: Absinthe.Type.Enum.Value.build/1
lib/absinthe/type/enum.ex:95: Absinthe.Type.Enum.build/1
lib/absinthe/schema/notation/writer.ex:91: Absinthe.Schema.Notation.Writer.type_functions/1
lib/absinthe/schema/notation/writer.ex:222: anonymous fn/2 in Absinthe.Schema.Notation.Writer.update_type_functions/3
(elixir) lib/map.ex:727: Map.update!/3
lib/absinthe/schema/notation/writer.ex:203: Absinthe.Schema.Notation.Writer.do_build_info/2
(elixir) lib/enum.ex:1826: Enum."-reduce/3-lists^foldl/2-0-"/3
expanding macro: Absinthe.Schema.Notation.Writer.__before_compile__/1
lib/acme/schema/types.ex:1: Acme.Schema.Types (module)
(elixir) lib/kernel/parallel_compiler.ex:121: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1
Hey @maennchen I'm going to include this under https://github.com/absinthe-graphql/absinthe/issues/410 I think.
Module attributes are actually incredibly tricky to work with in macros because while @foo :foo is itself a macro, it merely expands to Module.put_attribute which is a function, and the macro expansion tricks we've used heretofore won't work. Making module attributes work falls under Schema 1.5 goals.
Hi @benwilson512! I don't mean to rush you but when do you think we can see this in a new release? I use EctoEnum and it'd be great if I could do something like this:
enum :post_type, values: MyApp.Post.Type.__enum_map__()
I'm not sure if you've had a chance to look at how this should be done but I had a similar question for one of my own packages a while back. I can try going through the asbinthe code and send in a PR. Let me know what you think!
small workaround for this issue
values = [:foo, :bar]
enums = quote do
enum :myenum, values: unquote(values)
end
Macro.expand_once(enums, __ENV__)
Thank you very much @fertel.
Using expanded module attributes also works:
defmodule Enums do
@channels [:red, :green, :blue]
defmacro channels, do: Macro.expand(@channels, __CALLER__)
end
then
use Absinthe.Schema.Notation
require Enums
enum(:channel, values: Enum.channels())
You can also declare an EctoEnum with:
import EctoEnum
require Enums
defenum(Channel, :channel, Enums.channels())
If you need as values (or description) as well, the following macro works for me:
defmodule Help do
defmacro enum_values(values) do
expanded = Macro.expand(values, __CALLER__)
values =
Enum.map(expanded, fn {name, as} ->
quote do
value(unquote(name), as: unquote(as))
end
end)
quote(do: (unquote_splicing(values)))
end
end
You have to declare the enum values in an expanded module attribute:
defmodule Enums do
@channels [red: :r, green: :g, blue: :b]
defmacro channels, do: Macro.expand(@channels, __CALLER__)
end
Then you can declare your enum with:
use Absinthe.Schema.Notation
require Enums
require Help
enum :channel, do: Help.enum_values(Enums.channels())
or
enum :channel do
Help.enum_values(Enums.channels())
end
A description could be added in the list by using maps instead of keywords.
I've been using a similar macro:
defmacro enum_from_ecto(name, module) when is_atom(name) do
name = Macro.expand(name, __CALLER__)
module = Macro.expand(module, __CALLER__)
values = module.__enum_map__()
quote do
enum(unquote(name), values: unquote(values))
end
end
To call:
enum_from_ecto(:order_status, Order.StatusEnum)
This is still not working in Absinthe 1.5 and neither are the workarounds. Opened #946 to track this.
Most helpful comment
Thank you very much @fertel.
Using expanded module attributes also works:
then
You can also declare an EctoEnum with:
If you need
asvalues (ordescription) as well, the following macro works for me:You have to declare the enum values in an expanded module attribute:
Then you can declare your enum with:
or
A
descriptioncould be added in the list by using maps instead of keywords.