How to have predefined values (select) in an Ecto field?

I hope I am describing it properly. In django web framework one can do

GENDER_CHOICES = (
    ('m', 'Male'),
    ('f', 'Female'),
    ('c', 'Couple'),
)

class UserProfile(models.Model):
  # ... some fields
  gender = models.CharField(max_length=1, choices=GENDER_CHOICES)

In the above code it is defined a tuple of possible choices and the model field can only take one of the values “m”, “f” or “c”. The important thing is that GENDER_CHOICES does not represent a table in the database.

Is there an established pattern to do the same thing with an Ecto field?

1 Like

Well, I can think of couple of ways. First of all, this sort of thing can be handled on the database level. If using PostgreSQL, it has an “Enum” types https://www.postgresql.org/docs/9.2/static/datatype-enum.html.

But Ecto does not seem to implement it natively, and I think since it’s not portable between SQL databases, it never will. Some good person started a project to implement the custom type for Ecto/Enums here: https://github.com/gjaldon/ecto_enum

but I do not know how complete is that or is that usable at all. You’ll need to investigate.

The other option is to simply use the String/Varchar/Text type and enforce the values using Ecto’s validations mechanism, to allow only certain values:

https://hexdocs.pm/ecto/2.0.0/Ecto.Changeset.html#validate_inclusion/4

3 Likes

ecto_enum works quite well, I’d recommend it. :slight_smile:

1 Like