未为结构实现协议可枚举。如何将结构转换为可枚举?
Posted
技术标签:
【中文标题】未为结构实现协议可枚举。如何将结构转换为可枚举?【英文标题】:Protocol Enumerable not implemented for struct. How to convert the struct into an enumerable? 【发布时间】:2016-02-29 11:21:18 【问题描述】:我正在使用结构在 Phoenix / Elixir 应用程序中创建自定义模型。像这样:
defmodule MyApp.User do
defstruct username: nil, email: nil, password: nil, hashed_password: nil
end
new_user = %MyApp.Useremail: "email@example.com", hashed_password: nil, password: "secret", username: "ole"
为了将它与我的数据库适配器一起使用,我需要数据是可枚举的。结构显然不是。至少我收到这个错误:
(Protocol.UndefinedError) protocol Enumerable not implemented for %MyApp.User ...
所以我用理解来试试运气。这当然也不起作用,因为结构不可枚举(愚蠢的我)
enumberable_user = for key, val <- new_user, into: %, do: key, val
如何将数据转换为可枚举的地图?
【问题讨论】:
【参考方案1】:您可以使用Map.from_struct/1 在插入数据库时转换为地图。这将删除 __struct__
键。
您曾经能够派生 Enumerable 协议,但似乎是偶然的。 https://github.com/elixir-lang/elixir/issues/3821
哎呀,之前推导工作是个意外,我认为我们不应该修复它。也许我们可以更新 v1.1 更改日志以使其清楚,但我不会更改代码。
defmodule User do
@derive [Enumerable]
defstruct name: "", age: 0
end
Enum.each %Username: "jose", fn k, v ->
IO.puts "Got #k: #v"
end
【讨论】:
【参考方案2】:我创建了模块 make_enumerable 来解决这个问题:
defmodule Bar do
use MakeEnumerable
defstruct foo: "a", baz: 10
end
iex> import Bar
iex> Enum.map(%Bar, fn(k, v) -> k, v end)
[baz: 10, foo: "a"]
【讨论】:
以上是关于未为结构实现协议可枚举。如何将结构转换为可枚举?的主要内容,如果未能解决你的问题,请参考以下文章