Migrating an Enum in Vapor using AsyncMigration

51 Views Asked by At

How would one migrate an enum using AsyncMigration? There are a few examples online of migrating one using the EventLoopFuture, but my preference is to use Swift Concurrency.

1

There are 1 best solutions below

2
Sam Doggett On

After doing a bit of debugging, I was able to get everything working using AsyncMigration. I also find it a bit cleaner to read than using an EventLoopFuture.

Suppose we want to add an enum representing user roles:

public enum Role: String, Codable, Equatable {
    case appUser = "app_user"
    case admin = "admin"
}

You'd create a Fluent model and add the field:

@Enum(key: "role")
var role: Role

Lastly, you'd want to migrate it in two steps:

struct CreateUsers: AsyncMigration {

    func prepare(on database: Database) async throws {
        let role = try await database.enum("role")
            .case(User.Role.appUser.rawValue)
            .case(User.Role.admin.rawValue)
            .create()
        try await database.schema(User.schema)
            .id()
            // ...
            .field("role", role, .required, .custom("DEFAULT '\(User.Role.appUser.rawValue)'"))
            .create()
    }
    
    func revert(on database: Database) async throws {
        try await database.enum("role").delete()
        try await database.schema(User.schema).delete()
    }

}

I prefer to use the rawValue, to ensure everything is Strongly bound.

Also note I added .custom("DEFAULT '\(User.Role.appUser.rawValue)'") to the field initializer. This will default the database's column to be an app_user (optional).