我有一个 Ecto 架构,其中包括field :owned_by_id, :string. 我将该字段声明为字符串,因为我需要支持“abc123”等值以及“123”等值。
第二个参数是根据来自 的类型信息进行转换的参数映射
data。
在我的模块中,我定义changeset如下:
def changeset(struct, params \\ %{}) do
cast(struct, params, [:owned_by_id])
end
Run Code Online (Sandbox Code Playgroud)
当我这样做时:
MyModule.changeset(%MyModule{}, %{owned_by_id: 1})
Run Code Online (Sandbox Code Playgroud)
...我希望根据声明cast将该整数参数转换为字符串。owned_by_idfield
然而,我得到的是一个变更集,其中包括
errors: [owned_by_id: {"is invalid", [type: :string]}]
Run Code Online (Sandbox Code Playgroud)
我可以给Integer.to_string(1)自己打电话,但不应该cast处理这个吗?有没有办法让它自动处理这个问题?
虽然文档确实说参数是“根据类型信息进行转换”,但 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
...
Run Code Online (Sandbox Code Playgroud)
注意:我不建议这样做。在我看来,显式转换会更简单,除非您要实现像我上面链接的文档示例这样复杂的东西。