EctoEnum for ActiveRecord-like enums in Ecto updated!

Just in case anyone is looking for a way to use postgres enum types with ecto, here’s how (without any additional dependencies).

defmodule Invoice.Status do
  @moduledoc """
  The status of payment; whether the invoice has been paid or not.

  Enumeration members:
  - `:payment_automatically_applied`
  - `:payment_complete`
  - `:payment_declined`
  - `:payment_due`
  - `:payment_past_due`
  """

  @behaviour Ecto.Type

  statuses = [
    :payment_automatically_applied,
    :payment_complete,
    :payment_declined,
    :payment_due,
    :payment_past_due
  ] |> Enum.map(fn status ->
    {status, to_string(status)}
  end)

  @doc "Returns the underlying schema type for the custom type"
  @spec type :: :invoice_status
  def type, do: :invoice_status

  @doc "Casts the given input to the custom type"
  @spec cast(atom | binary) :: {:ok, atom} | :error
  def cast(status)

  for {atom, string} <- statuses do
    def cast(unquote(atom)), do: {:ok, unquote(atom)}
    def cast(unquote(string)), do: {:ok, unquote(atom)}
  end

  def cast(_other), do: :error

  @doc "Loads the given term into a custom type"
  @spec load(binary) :: {:ok, atom}
  def load(status)

  for {atom, string} <- statuses do
    def load(unquote(string)), do: {:ok, unquote(atom)}
  end

  @doc "Dumps the given term into an Ecto native type"
  @spec dump(atom | binary) :: {:ok, binary} | :error
  def dump(status)

  for {atom, string} <- statuses do
    def dump(unquote(atom)), do: {:ok, unquote(string)}
    def dump(unquote(string)), do: {:ok, unquote(string)}
  end

  def dump(_other), do: :error
end
9 Likes