为什么Ecto的`cast`不能将整数转换为字符串? [英] Why does Ecto's `cast` not convert an integer to a string?

查看:104
本文介绍了为什么Ecto的`cast`不能将整数转换为字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含 field:owned_by_id,:string 的Ecto模式。我将字段声明为字符串是因为我需要支持 abc123之类的值以及 123之类的值。



用于cast / 3的文档说:


第二个参数是根据数据的类型信息强制转换的参数映射。


在我的模块中,我定义 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆