Skip to content

Instantly share code, notes, and snippets.

@syamilmj
Created October 29, 2016 07:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save syamilmj/bbd8dd5b06c6ca7d1c2fa63e36df0d2d to your computer and use it in GitHub Desktop.
Save syamilmj/bbd8dd5b06c6ca7d1c2fa63e36df0d2d to your computer and use it in GitHub Desktop.
Add enum datatype support to Ecto
defmodule Inventory.Enum do
@moduledoc """
Provides macro to support Enum datatype with Ecto
## Usage
In your model:
import Inventory.Enum
defenum MyEnumStatus, draft: 0, published: 1, archive: 2
schema "posts" do
field :status, MyEnumStatus
end
To query:
from p in Post, where: p.status == ^:published
"""
defmacro defenum(module, enum) do
quote do
list = unquote(enum) |> Macro.escape
defmodule unquote(module) do
@behaviour Ecto.Type
@keylist for {k,v} <- list, into: %{}, do: {k,v}
@vallist for {k,v} <- list, into: %{}, do: {v,k}
def type, do: :integer
def cast(key) when is_atom(key) do
fetch(key, @keylist)
end
def cast(integer) when is_integer(integer), do: {:ok, integer}
def cast(_), do: :error
def load(val) when is_integer(val) do
fetch(val, @vallist)
end
def dump(integer) when is_integer(integer), do: {:ok, integer}
def dump(_), do: :error
defp fetch(key, map) do
if key in Map.keys(map) do
{:ok, Map.get(map, key)}
else
:error
end
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment