为什么Ecto的`cast`不能将整数转换为字符串? [英] Why does Ecto's `cast` not convert an integer to a string?
问题描述
我有一个包含 field:owned_by_id,:string
的Ecto模式。我将字段声明为字符串是因为我需要支持 abc123之类的值以及 123之类的值。
第二个参数是根据
数据
的类型信息强制转换的参数映射。
在我的模块中,我定义 changeset
像: > def changeset(struct,params \\%{})做
cast(struct,params,[:owned_by_id])
end
当我这样做时:
MyModule.changeset(%MyModule {},%{owned_by_id:1})
...我会期望 cast
根据字段将
声明。 owned_by_id
整数参数转换为字符串
但是,我得到的却是一个变更集,其中包括
错误:[owned_by_id:{无效,[类型::string]}]
我可以自己呼叫 Integer.to_string(1)
,但不应该
文档确实说参数是根据类型信息,则Ecto不会为整数->字符串实施转换。我的猜测是,这是因为当通过网络表单发送所有字段都以字符串形式到达的输入时,使用String-> Integer转换非常有用。
< hr>
如果要进行这种转换,可以创建自定义类型。该文档提供了一个实现类似功能的自定义类型的示例: https://github.com/elixir-ecto/ecto/blob/d40008db48ec26967b847c3661cbc0dbaf847454/lib/ecto/type.ex#L29-L40
您的类型应类似于:
def类型,请执行以下操作::string
当is_integer(integer)时执行def cast(integer)
{:ok,Integer.to_string(integer)}
end
当is_binary(string)时执行def cast(string),执行:{: OK,字符串}
def cast(_),执行::error
...
注意:我不建议这样做。我认为,除非您要实现类似我上面链接的文档示例之类的复杂功能,否则显式转换会更简单。
I have an Ecto schema that includes field :owned_by_id, :string
. I declared the field a string because I need to support values like "abc123" as well as values like "123".
The docs for cast/3 say:
The second argument is a map of params that are cast according to the type information from
data
.
In my module, I define changeset
like:
def changeset(struct, params \\ %{}) do
cast(struct, params, [:owned_by_id])
end
When I do this:
MyModule.changeset(%MyModule{}, %{owned_by_id: 1})
... I would expect cast
to turn that owned_by_id
integer param into a string, based on the field
declaration.
However, what I get instead is a changeset that includes
errors: [owned_by_id: {"is invalid", [type: :string]}]
I could call Integer.to_string(1)
myself, but shouldn't cast
handle that? Is there a way to have it handle this automatically?
While the docs do say that the params are "cast according to the type information", Ecto does not implement casting for Integer -> String. My guess would be that's because this is rarely needed while the String -> Integer conversion is useful for when the input is sent via a web form where all the fields arrive as strings.
You can create a custom type if you want this kind of conversion. The documentation has an example of a custom type that implements something similar: https://github.com/elixir-ecto/ecto/blob/d40008db48ec26967b847c3661cbc0dbaf847454/lib/ecto/type.ex#L29-L40
Your type would look something like:
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
...
Note: I wouldn't recommend doing this. In my opinion, an explicit conversion would be simpler unless you're implementing something complex like the documentation example I've linked to above.
这篇关于为什么Ecto的`cast`不能将整数转换为字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!