defmodule EctoEnumerize do @moduledoc """ Provides `EctoEnumerize.defenum/2` macro for defining an Enum Ecto type. """ @doc """ Defines a custom Enum `Ecto.Type`. """ @spec defenum(module(), key: integer()) :: Macro.t() defmacro defenum(module, enum) do quote do kw = unquote(enum) |> Macro.escape() defmodule unquote(module) do @behaviour Ecto.Type @atom_enum kw @string_enum for {atom, int} <- @atom_enum, into: %{}, do: {to_string(atom), atom} @int_enum for {atom, int} <- @atom_enum, into: %{}, do: {int, atom} def type(), do: :integer def cast(k) when is_atom(k) do if @atom_enum[k], do: {:ok, k}, else: :error end def cast(k) when is_binary(k) do if @string_enum[k], do: {:ok, @string_enum[k]}, else: :error end def cast(k) when is_integer(k) do if @int_enum[k], do: {:ok, @int_enum[k]}, else: :error end def cast(_k), do: :error def load(k) when is_integer(k) do v = @int_enum[k] if v, do: {:ok, v}, else: :error end def dump(k) when is_atom(k), do: {:ok, @atom_enum[k]} def get_enum(), do: @atom_enum end end end end