【问题标题】:Ecto custom types: How do I represent a field in a model as a specific type?Ecto 自定义类型:如何将模型中的字段表示为特定类型?
【发布时间】:2016-09-12 03:31:05
【问题描述】:

我有一个架构,我希望其中一个字段以 %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

遵循文档 (https://hexdocs.pm/ecto/Ecto.Type.html) 中的这些指南:

  • type 应该输出数据库类型的名称
  • cast 应该接收任何类型并输出您的自定义 Ecto 类型
  • load 应该接收 DB 类型并输出您的自定义 Ecto 类型
  • dump 应该会收到您的自定义 Ecto 类型并输出 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

现在我尝试将块保存到数据库:

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.cast/1中的所有成功案例中返回{:ok, cm}(其中cm%Cm{...}Cm.new(...))。

标签: elixir ecto


【解决方案1】:

Dogbert 提供的正确答案:返回 value 而不是 {:ok, value}

【讨论】:

    猜你喜欢
    • 2014-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 2020-03-17
    相关资源
    最近更新 更多