What's an easy way to share EctoEnum type with templates in forms select input?

First excuse me because I’m not very comfortable with English.

I got EctoEnum an extension to Ecto from here; https://github.com/gjaldon/ecto_enum.
Then I followed the readme instructions and now I have a StatusEnum type (registered: 0, active: 1, inactive: 2, archived: 3).

In my migrations file for a users table I add a column status and sert its type to integer since that’s the type expected by EctoEnum in database. (Though I would like to use string instead, but that’s okay)

Then in User model I set status field to StatusEnum type.

Until now all’s going well as expected. When I use a text input in new user form for status field, only expected entries are accepted (registered, active, inactive, archived).
But the problem is when I want to use form select instead of text input. The StatusEnum type have a method named enum_map which returns this list: [registered: 0, active: 1, inactive: 2, archived: 3].
So when providing this list to the form select, I got an invalid type error from the form validatior, on submit. I understand that’s a normal thing, since User model changeset is expecting a string entry for the status field instead of an integer as the list provided to the form select will be returning.

A solution could be providind by hand the suitable List to the form select, such as [“registered”, “active”, “inactive”, “archived”]. But If the StatusEnum type changes in future, I wiil have to update also my form template. I think that’s not very convenient.

Another solution that came to my mind will be setting User model status field type to integer. But then I won’t take advantage from the EctoEnum validators through StatusEnum.

I think the matter comes mainly from the fact I’m a newcomer to elixir, but please can you help me to find the best and simple way to handle this ?
Should I writte my own method, in addition to EctoEnum extension, to retrieve the form select options ?
Or should I drop this library and then what’s to do ?
Also I would like to be able to use french accented characters in the form select options. I’m mentionning that because I noticed that such characters can’t be used as elixir atoms.

I hope that my topic is more or less comprehensive. Thank you ^^

2 Likes

Just massage your enum_map return of [registered: 0, active: 1, inactive: 2, archived: 3] into the right format, like this: :slight_smile:

iex> [registered: 0, active: 1, inactive: 2, archived: 3] |> Enum.map(&to_string(elem(&1, 0)))
["registered", "active", "inactive", "archived"]

Although the html should accept atoms so the to_string step should not be necessary in any case. :slight_smile:

Honestly for enum’s though I like to use PostgreSQL Enumerations instead, can store things so they look like strings and get them back the same, but only accepts the subset. :slight_smile:

2 Likes

Thank you very much for your quick answer ! Finally I decide to go with another package instead of EctoEnum. Its called Exnumerator : https://github.com/KamilLelonek/exnumerator. Since I"m not using PostgreSQL Enumerations, I want to use string at least at the database side for the column status. Thie reason I’m avoiding PostgreSQL Enumerations is that I read that updating them could be a bit painful. What’s more on EctoEnum extension page, it’s said that there is no easy way to drop an PostgreSQL Enumerations value.

Anyway thank you again for the nice massaging tip. :slight_smile:

3 Likes

I’ve never had issues extending a PostgreSQL enum, what issues did you experience?

As for dropping a value, by dropping an enum value you would re-shuffle the internal ID of all that follow it, just like you would do if you dropped an enum value in any language that uses index backed enum’s (almost all), I just rename the unused ones to have a _deprecated_ in front of it. :slight_smile:

1 Like

Well I didn’t personally experience any issue with PostgreSQL enum. Probably issues were about old versions. In fact, before Phoenix/Elixir, lastely I didn’t really touch to database or migrations stuff. In Django/Python framework, I just create a model and the ORM create appropriate migrations for me.

With Ecto it’s different but I think I’ll get used to it. So how do you link your model with PostgreSQL Enumerations. Do you use EctoEnum extension ?

This is probably out of the topic, but I just found a way to finally use atoms with any string ! Elixir is just awesome, but it needs some learning effort. ^^
For example to use space in the atom I tried this and it works: atom = :"Atom with white some spaces"
And also it works with even accented characters. Though I tried with japanese characters without success. :smiley:

1 Like

I’m using enumerations in 2 areas right now, but both are just a set of strings, so I expose that to the Ecto side as just a :string, even though internally it is an enumeration. In the changeset I just validate to the fixed list that matches the enumeration, though what I should probably do also have it catch a database error of an invalid enumeration value so I would not have to hard code those. But I do not use any library for it, PostgreSQL makes it pretty natural for whatever type you want the enumeration to be exposed as. :slight_smile:

3 Likes