У меня есть схема, где я хочу, чтобы одно из полей представлялось в виде %Cm{value: 1.0}
(для сантиметров).Ecto custom types: как я могу представить поле в модели как конкретный тип?
я определил этот тип логотипо:
defmodule Db.Types.Cm do
alias Units.Cm
@behavior Ecto.Type
def type, do: :float
def cast(%Cm{value: integer}) when is_integer(integer) do
Cm.new(integer/1.0)
end
def cast(val = %Cm{value: float}) when is_float(float) do
val
end
def cast(number) when is_float(number), do: Cm.new(number)
def cast(number) when is_integer(number), do: Cm.new(number/1.0)
def cast(_), do: :error
def load(float) when is_float(float), do: Cm.new(float)
def dump(%Cm{value: float}) when is_float(float), do: float
def dump(%Cm{value: integer}) when is_integer(integer), do: (integer/1.0)
def dump(_), do: :error
end
Следуя этим указаниям из документации (https://hexdocs.pm/ecto/Ecto.Type.html):
type
должна вывести название типа DBcast
должен получать любой тип и выводить свой собственный тип Ectoload
должен получить тип DB и выходного пользовательского экто типаdump
должен получить свой собственный тип экто- и вывод типа DB
И следующая схема:
defmodule Db.Block do
schema "blocks" do
field :max_depth, Types.Cm
timestamps()
end
@fields ~w(max_depth)a
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @fields)
end
end
Теперь я попытайтесь сохранить блоки в db:
defmodule Db.BlockHelpers do
def new_block(attributes \\ %{}) do
block = Dict.merge(%{
max_depth: 2
}, attributes)
%Block{}
|> Block.changeset(block)
|> Repo.insert!
end
end
iex> new_block()
...> new_block(%{max_depth: Units.Cm.new(5.0)})
Однако я продолжаю получать ошибки:
** (CaseClauseError) no case clause matching: %Units.Cm{value: 2.0}
Я пробовал различные комбинации подходов, но не могу показаться, чтобы получить это право. Поэтому я не уверен на 100%, что понимаю документацию.
В конце дня, я хочу, чтобы иметь возможность пройти вокруг структурной структуры формы %Block{max_depth: %Units.Cm{value: 1.0}}
, где значение cm хранится как плавающая точка в базе данных (postgres).
Попробуйте вернуть '{: ok, cm}' (где 'cm' является'% Cm {...} 'или' Cm.new (...) ') из всех случаев успеха в' Db.Types .Cm.cast/1'. – Dogbert