Elixir EXTO自定义类型:如何将模型中的字段表示为特定类型?
我有一个模式,我希望其中一个字段以Elixir EXTO自定义类型:如何将模型中的字段表示为特定类型?,elixir,ecto,Elixir,Ecto,我有一个模式,我希望其中一个字段以%Cm{value:1.0}(厘米单位)的形式表示 我已定义此自定义类型: 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(va
%Cm{value:1.0}
(厘米单位)的形式表示
我已定义此自定义类型:
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
遵循文档()中的这些指导原则:
应输出数据库类型的名称type
应接收任何类型并输出您的自定义EXTO类型cast
应接收DB类型并输出自定义的EXTO类型load
应接收自定义的EXTO类型并输出DB类型dump
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
现在我尝试将块保存到数据库:
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\u depth:%Units.Cm{value:1.0}
的模型结构,其中Cm值作为浮点存储在数据库(postgres)中。Dogbert提供的正确答案:was返回值,而不是{ok,value}
尝试从Db.Types.cm.cast/1
中的所有成功案例中返回{:ok,cm}
(其中cm
是%cm{…}
或cm.new(…)
)。