Current section
Files
Jump to
Current section
Files
lib/ectonum.ex
defmodule Ectonum do
@moduledoc """
Adds a `defenum/2` macro for defining enum types for Ecto schemas.
"""
@doc """
Defines a custom `Ecto.Type` for enumerated fields.
## Usage
defmodule Profile do
import Ectonum
defenum GenderEnum, [:male, :female]
schema "profiles" do
field :gender, GenderEnum
end
end
In the above example the `:gender` field will cast both string and atom values matching any of the options specified in the enum type.
"""
defmacro defenum(module, values) when is_list(values) do
quote do
defmodule unquote(module) do
@behaviour Ecto.Type
def type, do: :string
def cast(term), do: Ectonum.cast(term, __valid_values__())
def load(term), do: Ectonum.load(term)
def dump(term), do: Ectonum.dump(term)
defp __valid_values__, do: unquote(values)
end
end
end
@spec cast(any, list) :: {:ok, atom} | :error
def cast(value, values) when is_atom(value) do
if value in values, do: {:ok, value}, else: :error
end
@doc false
def cast(value, values) when is_binary(value) do
atom = String.to_atom(value)
if atom in values, do: {:ok, atom}, else: :error
end
def cast(_, _), do: :error
@doc false
def load(string) when is_binary(string), do: {:ok, String.to_atom(string)}
def load(_), do: :error
@doc false
def dump(value) when is_binary(value), do: {:ok, value}
def dump(value) when is_atom(value), do: {:ok, Atom.to_string(value)}
def dump(_), do: :error
end