Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protocol Enumerable not implemented for struct. How to convert the struct into an enumerable?

I am using structs to create custom models in a Phoenix / Elixir app. Like so:

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

new_user = %MyApp.User{email: "[email protected]", hashed_password: nil, password: "secret", username: "ole"}

In order to use it with my database adapter, I need the data to be enumerable. Which a struct apparently isn't. At least I receive this error:

(Protocol.UndefinedError) protocol Enumerable not implemented for %MyApp.User{ ...

So I tried my luck using a comprehension. Which of course also doesn't work, because the struct isn't enumerable (stupid me)

enumberable_user = for {key, val} <- new_user, into: %{}, do: {key, val}

How can I convert the data to an enumerable map?

like image 841
Ole Spaarmann Avatar asked Nov 22 '25 08:11

Ole Spaarmann


1 Answers

You can use Map.from_struct/1 to do the conversion to a map at the point of insertion to the database. This will remove the __struct__ key.

You used to be able to derive the Enumerable protocol, but it seems that it was accidental. https://github.com/elixir-lang/elixir/issues/3821

Ouch, it was an accident that deriving worked before, I don't think we should fix it. Maybe we could update the v1.1 changelog to make it clear but I wouldn't do a code change.

defmodule User do
  @derive [Enumerable]
  defstruct name: "", age: 0
end

Enum.each %User{name: "jose"}, fn {k, v} ->
  IO.puts "Got #{k}: #{v}"
end
like image 122
Gazler Avatar answered Nov 23 '25 23:11

Gazler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!