Skip to content

Commit 472957e

Browse files
Merge pull request #26 from renatomassaro/allow-enum-values-to-be-defined-as-a-function
Allow Enum values to be defined as a function
2 parents 4b0bae6 + 7ae561d commit 472957e

5 files changed

Lines changed: 34 additions & 5 deletions

File tree

lib/feeb/db/type/enum.ex

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@ defmodule Feeb.DB.Type.Enum do
99
If a valid `format` is specified, keep as is. However, if one was not specified by the user, infer
1010
it based on the contents of the `values` entry. We assume all entries within `values` will share
1111
the same type (and we will crash otherwise).
12+
13+
We accept `values` being a function, as long as it is a function that returns a list. This might
14+
be useful if the application wants to avoid transitive compile-time dependencies.
1215
"""
16+
def overwrite_opts(%{values: values_fn} = opts, mod, identifier) when is_function(values_fn),
17+
do: overwrite_opts(%{opts | values: values_fn.()}, mod, identifier)
18+
1319
def overwrite_opts(%{format: format} = opts, _, _) do
1420
true = format in [:atom, :safe_atom, :string]
1521
opts
1622
end
1723

18-
def overwrite_opts(%{values: values} = opts, _, identifier) do
24+
def overwrite_opts(%{values: values} = opts, _, identifier) when is_list(values) do
1925
value_types =
2026
values
2127
|> Enum.map(fn value ->

priv/test/migrations/test/241020150400_all_types.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ CREATE TABLE all_types (
3030
list_nullable TEXT,
3131
enum TEXT,
3232
enum_nullable TEXT,
33-
enum_safe_atom TEXT
33+
enum_safe_atom TEXT,
34+
enum_fn TEXT
3435
) STRICT;

test/db/schema_test.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ defmodule DB.SchemaTest do
5959
:list_nullable,
6060
:enum,
6161
:enum_nullable,
62-
:enum_safe_atom
62+
:enum_safe_atom,
63+
:enum_fn
6364
] == AllTypes.__cols__()
6465
end
6566
end

test/db/type/enum_test.exs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,24 @@ defmodule Feeb.DB.Type.EnumTest do
77

88
describe "enum type" do
99
test "stores and loads correctly", %{shard_id: shard_id} do
10-
params = AllTypes.creation_params(%{enum: :one, enum_nullable: "baz"})
10+
params = AllTypes.creation_params(%{enum: :one, enum_nullable: "baz", enum_fn: :function})
1111

1212
# Enums are correctly casted
1313
all_types = AllTypes.new(params)
1414
assert all_types.enum == :one
1515
assert all_types.enum_nullable == "baz"
16+
assert all_types.enum_fn == :function
1617

1718
# Enums are correctly dumped and loaded
1819
DB.begin(@context, shard_id, :write)
1920
assert {:ok, db_all_types} = DB.insert(all_types)
2021
assert db_all_types.enum == :one
2122
assert db_all_types.enum_nullable == "baz"
23+
assert db_all_types.enum_fn == :function
2224

2325
# Values are stored as text in the database
24-
assert [["one", "baz"]] == DB.raw!("select enum, enum_nullable from all_types")
26+
assert [["one", "baz", "function"]] ==
27+
DB.raw!("select enum, enum_nullable, enum_fn from all_types")
2528
end
2629

2730
test "crashes if input is not a possible enum value" do
@@ -228,5 +231,22 @@ defmodule Feeb.DB.Type.EnumTest do
228231

229232
assert error =~ "Multiple types in enum"
230233
end
234+
235+
test "supports a function as value generator" do
236+
atom_values_fn = fn -> [:a, :b, :c] end
237+
str_values_fn = fn -> ["x", "y", "z"] end
238+
239+
opts = DB.Type.Enum.overwrite_opts(%{values: atom_values_fn, format: :safe_atom}, nil, nil)
240+
assert opts.values == [:a, :b, :c]
241+
assert opts.format == :safe_atom
242+
243+
opts = DB.Type.Enum.overwrite_opts(%{values: atom_values_fn}, nil, nil)
244+
assert opts.values == [:a, :b, :c]
245+
assert opts.format == :atom
246+
247+
opts = DB.Type.Enum.overwrite_opts(%{values: str_values_fn}, nil, nil)
248+
assert opts.values == ["x", "y", "z"]
249+
assert opts.format == :string
250+
end
231251
end
232252
end

test/support/db/schemas/all_types.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ defmodule Sample.AllTypes do
3636
{:enum, {:enum, values: [:one, :two, :three]}},
3737
{:enum_nullable, {:enum, values: ["foo", "bar", "baz"], nullable: true}},
3838
{:enum_safe_atom, {:enum, values: [:safe, :atom], format: :safe_atom, nullable: true}},
39+
{:enum_fn, {:enum, values: fn -> [:from, :a, :function] end, nullable: true}},
3940
{:virtual, {:integer, virtual: true}},
4041
{:virtual_with_after_read, {:integer, virtual: true, after_read: :load_virtual_integer}}
4142
]

0 commit comments

Comments
 (0)