Remi_Zacharias
Remi_Zacharias

Reputation: 328

Implementing an Enum as a PostgreSQL Column using SeaORM

I'm currently stuck on how to make one of my columns be an Enum of different payment types (Cash, Credit, Debit, etc.)

This is what I currently have for the table where manager is a reference to SchemaManager

       manager
            .create_table(
                Table::create()
                    .table(Orders::Table)
                    .if_not_exists()
                    (Creating a couple other columns)...
    // This line    .col(ColumnDef::new(Orders::PaymentType).enumeration(**PaymentOptions**, PaymentOptions::**iter()**).not_null())
                    (Just creating some more columns)...
                    .to_owned()
            )
            .await?;

In a seperate file, I have my enum PaymentOptions as such:

use strum_macros::EnumIter;

#[derive(Debug, EnumIter)]
pub enum PaymentOptions {
    Cash,
    Credit, 
    Debit, 
    Voucher,
}

I get 2 compiler-errors (under each of the bold sections), with the first (under PaymentOptions) being:

expected value, found enum PaymentOptionsrustcClick for full compiler diagnostic
mod.rs(6, 1): the enum is defined here
m20220101_000001_create_table.rs(24, 74): you might have meant to use one of the following enum variants: 
m20220101_000001_create_table::PaymentOptions::Cash, 
m20220101_000001_create_table::PaymentOptions::Credit, 
m20220101_000001_create_table::PaymentOptions::Debit, 
m20220101_000001_create_table::PaymentOptions::Voucher

And the second being:

no variant or associated item named `iter` found for enum `PaymentOptions` in the current scope
items from traits can only be used if the trait is in scoperustcClick for full compiler diagnostic

mod.rs(6, 1): variant or associated item `iter` not found for this enum

m20220101_000001_create_table.rs(1, 1): trait `IntoEnumIterator` which provides `iter` is implemented but 
not in scope; perhaps you want to import it: `use strum::IntoEnumIterator;`

I've looked into active_enum and ActiveEnumValue but I don't understand the documentation behind it enough to determine whether I can actually use these as a solution or how to implement them.

Maybe I can also continue using .enumeration:

**Documentation Excerpt**
pub fn enumeration<N, S, V>(&mut self, name: N, variants: V) -> &mut ColumnDef
where
    N: IntoIden,
    S: IntoIden,
    V: IntoIterator<Item = S>,
Set column type as enum.

But its unclear what it really wants passed in as a parameter to me.

Upvotes: 0

Views: 534

Answers (1)

Remi_Zacharias
Remi_Zacharias

Reputation: 328

After digging around a while, I found there's a couple ways to do it, and you really just have to try each of them because some of them don't work for no real apparent reason sometimes and it also depends on the database you're using (mySQL, PostgreSQL, etc.), but this here should explain most of it: https://www.sea-ql.org/SeaORM/docs/next/generate-entity/enumeration/

I found the easiest way (using PostgreSQL), was to create the enum like so:

#[derive(DeriveIden)]
#[sea_orm(enum_name = "payment_options")]
pub enum PaymentOptions {
    #[sea_orm(iden = "payment_options")]
    Enum,
    #[sea_orm(iden = "cash")]
    Cash,
    #[sea_orm(iden = "credit")]
    Credit, 
    #[sea_orm(iden = "debit")]
    Debit, 
    #[sea_orm(iden = "voucher")]
    Voucher,
} 

Where the most important part is just to make sure you include enum_name and DeriveIden.

Then you can go ahead and create it as a new type like this:

        manager
            .create_type(
                Type::create()
                    .as_enum(PaymentOptions::Enum)
                    .values(
                        [
                            PaymentOptions::Cash, 
                            PaymentOptions::Credit, 
                            PaymentOptions::Debit, 
                            PaymentOptions::Voucher
                        ]
                    )
                    .to_owned(),
            )
            .await?;

There are other ways to create the new type but this is the most straightforward and reliable method in my opinion.

Then I just needed to implement it while creating the table like this:

.col(ColumnDef::new(Orders::PaymentType).custom(PaymentOptions::Enum).not_null())

For anyone else with the same issue, I'd recommend just reading through the documentation thouroughly from the link I attached as other methods may work better for you

Upvotes: 2

Related Questions