From 80f2660f660595f25fdc04b122f3ad3696b16429 Mon Sep 17 00:00:00 2001 From: Vince Foley Date: Sun, 3 Jan 2021 00:11:19 -0800 Subject: [PATCH] Hack - attempt at support for dynamic Enum values --- .formatter.exs | 3 +- lib/absinthe/blueprint/schema.ex | 2 +- .../blueprint/schema/enum_type_definition.ex | 42 ++++++++++++++----- lib/absinthe/schema/notation.ex | 5 +-- test/absinthe/type/enum_test.exs | 14 +++++++ 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/.formatter.exs b/.formatter.exs index 02e4e0cdbd..60e5d98769 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -43,7 +43,8 @@ locals_without_parens = [ types: 1, union: 3, value: 1, - value: 2 + value: 2, + values: 1 ] [ diff --git a/lib/absinthe/blueprint/schema.ex b/lib/absinthe/blueprint/schema.ex index f3e4748558..745366e4c8 100644 --- a/lib/absinthe/blueprint/schema.ex +++ b/lib/absinthe/blueprint/schema.ex @@ -145,7 +145,7 @@ defmodule Absinthe.Blueprint.Schema do end defp build_types([{:values, values} | rest], [enum | stack], buff) do - enum = Map.update!(enum, :values, &(values ++ &1)) + enum = Map.update!(enum, :values, &(List.wrap(values) ++ &1)) build_types(rest, [enum | stack], buff) end diff --git a/lib/absinthe/blueprint/schema/enum_type_definition.ex b/lib/absinthe/blueprint/schema/enum_type_definition.ex index 046de5bb79..a3a7cd5d1e 100644 --- a/lib/absinthe/blueprint/schema/enum_type_definition.ex +++ b/lib/absinthe/blueprint/schema/enum_type_definition.ex @@ -42,17 +42,37 @@ defmodule Absinthe.Blueprint.Schema.EnumTypeDefinition do end def values_by(type_def, key) do - for value_def <- type_def.values, into: %{} do - value = %Absinthe.Type.Enum.Value{ - name: value_def.name, - value: value_def.value, - enum_identifier: type_def.identifier, - __reference__: value_def.__reference__, - description: value_def.description, - deprecation: value_def.deprecation - } - - {Map.fetch!(value_def, key), value} + for value_def <- List.flatten(type_def.values), into: %{} do + case value_def do + %Blueprint.Schema.EnumValueDefinition{} -> + value = %Absinthe.Type.Enum.Value{ + name: value_def.name, + value: value_def.value, + enum_identifier: type_def.identifier, + __reference__: value_def.__reference__, + description: value_def.description, + deprecation: value_def.deprecation + } + + {Map.fetch!(value_def, key), value} + + raw_value -> + name = raw_value |> to_string() |> String.upcase() + + value_def = %{ + name: name, + value: raw_value, + identifier: raw_value + } + + value = %Absinthe.Type.Enum.Value{ + name: name, + value: raw_value, + enum_identifier: type_def.identifier + } + + {Map.fetch!(value_def, key), value} + end end end diff --git a/lib/absinthe/schema/notation.ex b/lib/absinthe/schema/notation.ex index 546bdee052..ac277e2cc1 100644 --- a/lib/absinthe/schema/notation.ex +++ b/lib/absinthe/schema/notation.ex @@ -1494,10 +1494,7 @@ defmodule Absinthe.Schema.Notation do values = values |> expand_ast(env) - |> Enum.map(fn ident -> - value_attrs = handle_enum_value_attrs(ident, [], env) - struct!(Schema.EnumValueDefinition, value_attrs) - end) + |> wrap_in_unquote put_attr(env.module, {:values, values}) end diff --git a/test/absinthe/type/enum_test.exs b/test/absinthe/type/enum_test.exs index 660f0cabd1..6b1109446b 100644 --- a/test/absinthe/type/enum_test.exs +++ b/test/absinthe/type/enum_test.exs @@ -56,6 +56,12 @@ defmodule Absinthe.Type.EnumTest do value :blue, as: color(:blue) end + enum :dynamic_color_list do + values color_list() + end + + def color_list, do: [:purple, :orange, :yellow] + def color(:red), do: {255, 0, 0} def color(:green), do: {0, 255, 0} def color(:blue), do: {0, 0, 255} @@ -89,6 +95,14 @@ defmodule Absinthe.Type.EnumTest do assert %Type.Enum.Value{name: "GREEN", value: {0, 255, 0}} = type.values[:green] assert %Type.Enum.Value{name: "BLUE", value: {0, 0, 255}} = type.values[:blue] end + + test "values can be defined dynamically too" do + type = TestSchema.__absinthe_type__(:dynamic_color_list) + + assert %Type.Enum.Value{name: "YELLOW"} = type.values[:yellow] + assert %Type.Enum.Value{name: "PURPLE"} = type.values[:purple] + assert %Type.Enum.Value{name: "ORANGE"} = type.values[:orange] + end end describe "enum value description evaluation" do