为什么 Ecto 的 `cast` 不能将整数转换为字符串?
Why does Ecto's `cast` not convert an integer to a string?
我有一个包含 field :owned_by_id, :string
的 Ecto 模式。我将该字段声明为字符串,因为我需要支持 "abc123" 之类的值以及“123”之类的值。
The second argument is a map of params that are cast according to the type information from 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
不应该处理吗?有没有办法让它自动处理这个问题?
虽然文档确实说参数是 "cast according to the type information",但 Ecto 没有为 Integer -> String 实现转换。我的猜测是,这是因为很少需要这样做,而字符串 -> 整数转换对于通过 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
...
注意:我不建议这样做。在我看来,显式转换会更简单,除非您要实现像我上面链接的文档示例那样复杂的东西。
如果你想要一个即插即用的解决方案,你可以使用我创建的这个十六进制包。 https://github.com/luizParreira/ecto_cast_to_string
我有一个包含 field :owned_by_id, :string
的 Ecto 模式。我将该字段声明为字符串,因为我需要支持 "abc123" 之类的值以及“123”之类的值。
The second argument is a map of params that are cast according to the type information from
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
不应该处理吗?有没有办法让它自动处理这个问题?
虽然文档确实说参数是 "cast according to the type information",但 Ecto 没有为 Integer -> String 实现转换。我的猜测是,这是因为很少需要这样做,而字符串 -> 整数转换对于通过 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
...
注意:我不建议这样做。在我看来,显式转换会更简单,除非您要实现像我上面链接的文档示例那样复杂的东西。
如果你想要一个即插即用的解决方案,你可以使用我创建的这个十六进制包。 https://github.com/luizParreira/ecto_cast_to_string