【问题标题】:Why does Ecto's `cast` not convert an integer to a string?为什么 Ecto 的 `cast` 不能将整数转换为字符串?
【发布时间】:2016-11-15 15:24:23
【问题描述】:

我有一个包含field :owned_by_id, :string 的 Ecto 架构。我将该字段声明为字符串,因为我需要支持像“abc123”这样的值以及像“123”这样的值。

docs for cast/3 说:

第二个参数是根据来自data 的类型信息转换的参数映射。

在我的模块中,我将changeset 定义为:

def changeset(struct, params \\ %{}) do
  cast(struct, params, [:owned_by_id])
end

当我这样做时:

MyModule.changeset(%MyModule{}, %{owned_by_id: 1})

...我希望cast 会根据field 声明将owned_by_id 整数参数转换为字符串。

但是,我得到的是一个变更集,其中包括

errors: [owned_by_id: {"is invalid", [type: :string]}]

我可以自己打电话给Integer.to_string(1),但不应该cast 处理吗?有没有办法让它自动处理?

【问题讨论】:

    标签: elixir ecto


    【解决方案1】:

    如果你想要一个即插即用的解决方案,你可以使用我创建的这个十六进制包。 https://github.com/luizParreira/ecto_cast_to_string

    【讨论】:

      【解决方案2】:

      虽然文档确实说参数是“根据类型信息强制转换的”,但 Ecto 没有为 Integer -> String 实现强制转换。我的猜测是因为这很少需要,而 String -> Integer 转换对于通过所有字段都以字符串形式到达的 Web 表单发送输入时很有用。


      如果您想要这种转换,您可以创建自定义类型。该文档有一个实现类似功能的自定义类型示例:https://github.com/elixir-ecto/ecto/blob/d40008db48ec26967b847c3661cbc0dbaf847454/lib/ecto/type.ex#L29-L40

      你的类型应该是这样的:

      def type, do: :string
      
      def cast(integer) when is_integer(integer) do
        {:ok, Integer.to_string(integer)}
      end
      def cast(string) when is_binary(string), do: {:ok, string}
      def cast(_), do: :error
      
      ...
      

      注意:我不建议这样做。在我看来,显式转换会更简单,除非您要实现一些复杂的东西,比如我上面链接到的文档示例。

      【讨论】:

      • 听起来像个错误。
      猜你喜欢
      • 2021-05-09
      • 1970-01-01
      • 1970-01-01
      • 2018-01-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-13
      • 1970-01-01
      • 2017-04-09
      相关资源
      最近更新 更多