Вам нужно создать тип Ecto для каждого перечисления postgresql. В определении схемы у вас просто есть тип :string
. В миграциях вы устанавливаете тип как имя модуля. Это может стать очень утомительно, хотя, так что у меня есть следующий макрос в моем проекте, который использует PostGreSQL перечислений:
defmodule MyDB.Enum do
alias Postgrex.TypeInfo
defmacro defenum(module, name, values, opts \\ []) do
quote location: :keep do
defmodule unquote(module) do
@behaviour Postgrex.Extension
@typename unquote(name)
@values unquote(values)
def type, do: :string
def init(_params, opts), do: opts
def matching(_), do: [type: @typename]
def format(_), do: :text
def encode(%TypeInfo{type: @typename}=typeinfo, str, args, opts) when is_atom(str), do: encode(typeinfo, to_string(str), args, opts)
def encode(%TypeInfo{type: @typename}, str, _, _) when str in @values, do: to_string(str)
def decode(%TypeInfo{type: @typename}, str, _, _), do: str
def __values__(), do: @values
defoverridable init: 2, matching: 1, format: 1, encode: 4, decode: 4
unquote(Keyword.get(opts, :do, []))
end
end
end
end
Возможное использование:
import MyDB.Enum
defenum ColorsEnum, "colors_enum", ~w"blue red yellow"
ColorsEnum
будет имя модуля, "colors_enum"
будет enum name internal to Postgresql: вам нужно будет добавить инструкцию для создания типа перечисления в ваших миграциях базы данных. Конечным аргументом является список значений перечисления. Я использовал сигалью ~w
, которая разделит строку пробелом, чтобы показать, насколько это может быть кратким. Я также добавил предложение, которое преобразует значения атомов в строковые значения, когда они проходят через схему Ecto.
Похоже, что 'ecto_enum' больше не поддерживается – ryanwinchester