Protocol Enumerable没有为struct实现。如何将结构转换为可枚举的?

时间:2015-11-26 11:21:28

标签: erlang elixir phoenix-framework

我使用结构在Phoenix / Elixir应用程序中创建自定义模型。像这样:

defmodule MyApp.User do
  defstruct username: nil, email: nil, password: nil, hashed_password: nil
end

new_user = %MyApp.User{email: "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}

如何将数据转换为可枚举的地图?

2 个答案:

答案 0 :(得分:3)

您可以使用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 %User{name: "jose"}, fn {k, v} ->
  IO.puts "Got #{k}: #{v}"
end

答案 1 :(得分:0)

我创建了模块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"]