【问题标题】:Custom Types in ElixirElixir 中的自定义类型
【发布时间】:2016-08-23 23:55:13
【问题描述】:

我有一个玩具项目用来帮助我学习 Elixir/Phoenix。

我正在从 csv 导入一些数据,如果根据我的变更集它们是有效的,我想将这些记录插入到数据库中。

我的问题是,有时通常包含整数的列之一将具有“n/a”。这会导致变更集无效,因为它应该。

我不确定 Elixir 处理此问题的标准方法是什么。

在这些情况下,我只想将“n/a”转换为 0。

您通常会为此编写一个自定义类型来执行该转换吗?

https://hexdocs.pm/ecto/Ecto.Type.html

在 Rails 中,我可能会在模型上使用自定义设置器或 before_save 或其他方式解决此问题。

【问题讨论】:

    标签: elixir ecto


    【解决方案1】:

    我会在模型的 changeset 函数中通过“修复”params 来执行此操作,然后将其发送到 cast 进行验证。

    带有:count 整数字段的示例模型:

    def changeset(struct, params \\ %{}) do
      struct
      |> cast(fix_params(params), [:count])
      |> validate_required([:count])
    end
    
    defp fix_params(%{count: "n/a"} = params), do: %{params | count: 0}
    defp fix_params(params), do: params
    

    演示:

    iex(1)> Counter.changeset(%Counter{}, %{count: 123})
    #Ecto.Changeset<action: nil, changes: %{count: 123}, errors: [],
     data: #MyApp.Counter<>, valid?: true>
    iex(2)> Counter.changeset(%Counter{}, %{count: "n/a"})
    #Ecto.Changeset<action: nil, changes: %{count: 0}, errors: [],
     data: #MyApp.Counter<>, valid?: true>
    iex(3)> Counter.changeset(%Counter{}, %{count: "foo"})
    #Ecto.Changeset<action: nil, changes: %{},
     errors: [count: {"is invalid", [type: :integer]}], data: #MyApp.Counter<>,
     valid?: false>
    

    如果您希望将任何个非整数值转换为0,您可以这样做:

    defp fix_params(%{count: count} = params) when not is_integer(count), do: %{params | count: 0}
    defp fix_params(params), do: params
    

    演示:

    iex(1)> Counter.changeset(%Counter{}, %{count: "foo"})
    #Ecto.Changeset<action: nil, changes: %{count: 0}, errors: [],
     data: #MyApp.Counter<>, valid?: true>
    

    【讨论】:

    • 谢谢@Dogbert!我没有看到很多关于何时使用自定义类型的好例子。这是最热门的learningelixir.joekain.com/custom-types-in-ecto。我想使用自定义类型与“更清洁”功能的决定归结为您需要做什么的复杂性?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    • 2021-01-25
    • 2018-07-31
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    相关资源
    最近更新 更多