Skip to content

Checker that makes sure that enum type is used to store ActiveRecord's enumsΒ #169

@toydestroyer

Description

@toydestroyer

Let's extract our discussion from #160.

One of the things that I want to enforce in the project I'm working on right now is to stop using ActiveRecord's default integer enums and use strings with an actual enum type in the database (we're using PostgreSQL).

Regarding the general pros and cons of enum columns over integers/strings. I did a quick research (aka googled "postgresql enum pros and cons") and found this question on StackOverflow: https://stackoverflow.com/q/2318123

If I may just quote some of the answers from there:

The advantages of enums are:

  • Performance is better. You can just display what you get out of the core table instead of either having a separate lookup table that translates a code to a value or having app logic that translates a code to a value. This can be especially useful in datawarehouse applications.
  • Ad hoc SQL is easier to write

The disadvantages are:

  • Encoding display values into your database ddl is bad form. If you translate the enum value into a different display value in your app code, then you lost a lot of the advantages of using enums.
  • Adding values requires DDL changes
  • Makes language localization difficult
  • Database portability is decreased

and this one:

Advantages

  • Reduce Storage: Postgres uses only 1 byte per tuple when 255 or less ENUM elements are defined or 2 bytes for 256~65535 elements. This is because, rather that storing the constant literal of the value, Postgres stores the index in the ordered set of that value. For very large tables, this might prove to be a significant storage space save.
  • Arbitrary sorting:
CREATE TABLE opening_hours(
    week_day ENUM ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
    opening_time TIME,
    closing_time TIME
);

If you sort by week_day it will sort in the order you specified which is convenient in the above case.

  • Cheap constraints: Instead of doing checking in your application code or some complicated db constraint, enums check that only certain values are added in a cheap way.

Disadvantages

  • The list of options CANNOT be controlled by end-users since ENUM is part of the schema
  • An additional query is required to see the list of options
  • String operations and functions do not work on ENUM This is due to ENUM being a separate data type from the built-in data types like NUMERIC or TEXT. This can be overcome by casting ENUM values to TEXT when being operated. However, it can be a pain when using ORM.

In my case, this is definitely a win! But I understand that this is not for everyone. Especially considering that Rails added an API to create enum columns only from version 7, and only for PostgreSQL: rails/rails@4eef348. And it doesn't provide an API for adding/deleting/changing values once an enum is created. So you have to write raw SQL in your migration files or use third-party gems (#1, #2).

So what does everyone thinks about having such a checker as a part of the DatabaseConsistency gem? It might be disabled by default so people are cautious about enforcing it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions