Eiji

Eiji

Introducing Enumex: an advanced enum library

Yes, one more library for working with enums and also my 2nd enum library!

Introduction

My first library was really simple and was mainly intended for personal usage. I did not even expected that other people would use it. This one is completely different as I found that there is still something to do in this place. First of all this library was intended to be ecto-postgres-enum ~> 2.0, but way too many things changed.

The first thing to note is that it’s not intended to work only for PostgreSQL database and it even does not require any database. There are lots of helpful features which could be used as same as ecto without ecto_sql and that’s mainly why it’s not just another version of ecto-postgres-enum.

Try it

For now this library depends on master branch of ecto_sql, so I’m unable to release it as a hex package. For now please give it a try by cloning a GitLab repository:

This is only a release candidate and gives only preview on what I would like to provide in final release. Based on contribution it may change at any time before 1.0.0 stable release. For each release candidate I would add a git tag.

Migrations

However the true power of this library comes with ecto_sql support. The one of main features are migrations … fully reversible migrations! It’s not only about create and drop enum, but also add and drop value. I have written test to ensure that every migration does not cause problem with existing databases, but saying that is like don’t saying anything … You may wonder what happens if we would like to drop value which is already used, but this use case is also covered and tested!

My code for migrations is based on few articles which describes a safely work on database enum and here is one of them:

How does it work in migration file? It’s as simple as calling just one function!

Enumex.Ecto.Migration.drop_value(adapter, prefix, name, repo, value, default)

At this point you may be confused … How could it be reversible? Of course it’s not possible to turn back value for each row, but this is normal and same result you would have working in raw PostgreSQL console. This library focused on what database is able to do and offer such features in as simple as possible solutions.

This one feature took for me lots of time especially that ecto_sql previously blocked me in this specific scenario. Fortunately thanks to @josevalim this has been solved in master branch of ecto_sql.

Tasks

Of course there is more interesting feature … What would you say if you could simply diff updated your enum in Elixir just now with values which database is storing? Yes, it’s possible! Take a look at enumex.gen.migration mix task. It’s not only automatically detecting value add and drop, but also rename!

Other features

I could describe here all of features, but it could turn into a series of blog posts, so I simply list them all:

  1. Constants-like macros
    In response to: Using Enums as constants · Issue #87 · gjaldon/ecto_enum · GitHub

  2. Built-in absinthe support! Everything you need is to import type from YourEnum.Absinthe module.
    In response to: Dynamically generate graphql types · Issue #78 · gjaldon/ecto_enum · GitHub

  3. Migrations - except those already described there are few more helpful functions.

  4. Ecto support

  5. Lots of other debug functions, guards, work with indexes and more …

Database support

For now I’m only supporting PostgreSQL, but I have a plans to change it in next release candidates. However my knowledge about other databases is limited and it could take for me some time. I have take a look at MySQL and … do I need to comment it? :077:

This library is intended for database like PostgreSQL which provides a reasonable API. Ok, but what if other databases? I have an idea here. I can implement a Enumex.Adapters.SQLTable which would provide a __using__/1 macro for final adapters. In this way I would be able to add support not only for MySQL, but SQLite also does not looks so problematic with such solution.

Anyway as said I have not much experience with other databases (at least in enum topic), so I it would be really nice if someone could help with adding support for other adapters.

Future plans

As already said I’m planning to add at least one helper module called Enumex.Adapters.SQLTable and I would write (just for an example) an implementation for PostgreSQL so other developer may see how to deal with it. This mean that there would be at least one release candidate. What will come later I’m not sure, but I would really like to release it on hex as soon as possible even if it would be only for release candidate test purposes.

Have a nice day! :smiley:

Related

I would like to provide a list of issues and pull requests less or more related to enumex library.

This one I noticed when working with enumex.gen.enum mix task as ecto.gen.enum was a really good source of inspiration:

The blocking flush() bug and new execute usage:

A confusing error of wrongly emitted Erlang AST:

Once again I would like to thank @josevalim for all his help as without him really important parts of this library would not work. Also without it this library would would not be released so fast and most probably it could have a different form.

Feel free in case of any question. I would try to reply to all of them as soon as possible. Hope my work would help in future also in production environments.

Most Liked

unsek

unsek

Is this still being maintained?

Eiji

Eiji

Yes, I have even plans for next release candidate (which most probably would be final version) when 2 things would happen:

  1. ecto would release a new version with this PR merged
    https://github.com/elixir-ecto/ecto/pull/3339
  2. Temperature here would be lower :wink:

Lots of things happen in last 7 months and I was not focused on next release candidate.I have started working on it and already made 1/3 of things on my TODO list locally.

I can say already that final version would have 4 scenarios:

  1. Advanced (based on Enumex.Advanced.Adapter behaviour) - that is for optimizations on db side - like support for PostgreSQL custom type (i.e. create type … syntax)

  2. Custom - case when enum values are stored in database table - that’s my concept of custom enum il.e. Advanced scenario, but similarly to Simple useful when Enumex.Advanced.Adapter cannot be implemented. You may want to save more information in database or add for example constraints.

  3. Simple - similar to Advanced, but for cases when implementing Enumex.Advanced.Adapter is not possible (MySQL) - you would be able to store plain integer (index in enum) or string (value in enum)

  4. Extra support for Ecto.ParameterizedType and :enum (see PR) - due to how ecto would solve things it would work as same as Simple, but would have a bit different API (you would need to pass schema and field names instead of working on each enum module)

Each scenario is completely different and depends on few things:

  1. If you have legacy codebase with any of such scenario
  2. If you need to use specific database i.e. project requirements
  3. If for some reason you need to use older versions of Ecto
  4. If you want to use Ecto.ParameterizedType and :enum

Once next release candidate would be released I would like to know:

  1. Do you have any other scenario (especially in prod)?
  2. Would it work with ecto version 2.x? Originally there were no plans for it, but I will check how much work I would need to do in order to add backwards compatibility.
  3. Do you have some other suggestions? Improvements? Bugs?

Where Next?

Popular in Libraries Top

zoltanszogyenyi
Hey everyone :wave: Excited to join this forum - I am one of the founders and current project maintainers of a popular and open-source U...
New
kevinlang
Hey all, We have made an Ecto3 Adapter for SQLite3, ecto_sqlite3! We have successfully on-boarded the full suite of integration tests (...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
OvermindDL1
Been making an MLElixir thing (not released yet…) for fun in spare time in the past day. I’m just trying to see how much I can get an ML...
132 13487 106
New
pkrawat1
Presenting Aviacommerce, open source e-commerce platform in Elixir Aviacommerce is an open source e-commerce platform in Elixir. We at...
New
woutdp
Hi! I wanted to introduce my latest project LiveSvelte. It allows you to render Svelte inside LiveView with end-to-end reactivity. It’s ...
New
wfgilman
I’ve cleaned up and open sourced three financial libraries I was using for my company. They are bindings for the APIs of these three comp...
New
Hal9000
Here is my first stab at this. README pasted below. https://github.com/Hal9000/elixir_random Comments and critiques are welcome. Th...
New
mattludwigs
Grizzly is a library for working with Z-Wave devices. Z-Wave is a low-frequency radio protocol for controlling smart home devices on a me...
New
versilov
Could not wait for the missing Elixir ML libraries to appear, so, I wrote one myself, taking https://github.com/sdwolfz/exlearn as a foun...
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

Sub Categories:

We're in Beta

About us Mission Statement