1
私はフィールドの1つを%Cm{value: 1.0}
(センチメートル単位)の形で表現したいと思うスキーマを持っています。 DBタイプの名前が Ectoカスタムタイプ:モデル内のフィールドを特定のタイプとして表現するにはどうすればよいですか?
cast
出力がすべき
type
必要があります:ドキュメント(https://hexdocs.pm/ecto/Ecto.Type.html)から、これらのガイドラインに続いて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
:私はこの、カスタマーのタイプを定義している
任意のタイプを受け取り、カスタムEctoタイプを出力する
load
カスタムエクトタイプと出力DBタイプ
そして、次のスキーマ受けるべき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
をI 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)の浮動小数点として格納されています。
'Db.Typesのすべての成功事例から' {cm: 'が'%Cm {...} 'や' Cm.new(...) 'を返すようにしてください。 .Cm.cast/1'。 – Dogbert