Converting Changeset.errors to message for UI


I am struggling to work out some pattern matching. I am using Changeset.traverse_errors to extract and error as a map:

%{email: ["Email has already been registered"]}

I want to convert that to a string and put in a flash message but can’t seem to get it right. I am trying to do something like:

{atom_tostring(key), [ msg ]} = %{email: ["Email has already been registered"]}

Some guidence will be appreciated.

email is an atom in the map you have posted there. If it were a string it would be:

%{"email" => ["Email has already been registered"]}

So when you call atom_tostring/1 (which I assume is just a wrapper around to_string/1?), the pattern match will be:

{"email", [msg]} = %{email: ["Email has already been registered"]}

The pattern would match as: “A tuple of the string ‘email’ and an array of exactly one item”. What you want is “the value associated with the key :email, which is an array with exactly one item in it”:

%{email: [msg]} = %{email: ["Email has already been registered"]}

… and if you try that in iex you’ll see that msg now is bound to the value “Email has already been registered”.

However… if there is more than one entry in that array, it still won’t match, and instead what may want is:

%{email: [msg | _]} = %{email: ["Email has already been registered"]}

That | means “everything else after the first element in the list”, and the _ binds that “everything else” to the “ignore this” non-variable (meaning it just gets dropped). This will continue to match even multi-entry arrays:

> %{email: [msg | _]} = %{email: ["Email has already been registered", "Something else"]}
> msg
"Email has already been registered"

Of course, this will not match an empty array, so beware:

%{email: [msg | _]} = %{email: []}
** (MatchError) no match of right hand side value: %{email: []}

But there you go … hopefully that gets you a step further along :slight_smile:

1 Like

Fantastic thank you. You are correct , the email key is an atom. Is there a way I can get the value of teh key as a string so I can build an error message regardless of the value of the key atom?

Thanks in advance

If you are asking how to convert an atom into a string:

iex(1)> f = :some_atom
iex(2)> to_string(f)
iex(3)> "#{f}"
1 Like