Skip to content

Latest commit

 

History

History
112 lines (80 loc) · 2.73 KB

Fluent-Model-Convenience-Extensions.md

File metadata and controls

112 lines (80 loc) · 2.73 KB

Fluent Model Extensions

FieldsProvidingModel

How to stop suffering from string literals in Fluent Models' Fields

Allows to create Model's fields as an enum and then safely use it without hassling with string literals and suffering from fat fingers.

extension User: FieldsProvidingModel {
    enum Fields: String, FieldKeyRepresentable {
        case username
    }
}

final class User: Model, Content {
    static let schema = "users"

    @ID(key: .id)
    var id: UUID?

    @Field(key: Fields.username.key)
    var username: String?
    
}
    
 extension User: InitMigratableSchema {
    static func prepare(on schemaBuilder: SchemaBuilder) -> EventLoopFuture<Void> {
        return schemaBuilder
            .id()
            .field(Fields.username.key, .string)
            .create()
    }
}

InitMigratableSchema

How to stop suffering from Fluent Models' initial migrations boilerplate

Easy-breazy stuff for creating initial migrations in three simple steps.

  1. Make your model conform to InitMigratableSchema protocol, by implementing static prepare(...) method (almost as usual)
extension User: InitMigratableSchema {
    static func prepare(on schemaBuilder: SchemaBuilder) -> EventLoopFuture<Void> {
        return schemaBuilder
            .id()
            .field(Fields.username.key, .string)
            .create()
    }
}
  1. Add initial migration for the model in your configuration file:
func configureDatabaseInitialMigrations(_ app: Application) {
    app.migrations.add(User.createInitialMigration()) 
}

SiblingRepresentable

How to stop suffering from Siblings pivot models boiler plate

Short-cut for creating many-to-many relations.

  1. Define whatever as SiblingRepresentable (enum for example)
extension Todo {
    enum Relations {
        enum RelatedTags: SiblingRepresentable {
            typealias From = Todo
            typealias To = Tag
            typealias Through = SiblingModel<Todo, Tag, Self>
        }
    }
}
  1. Add corresponding property with @Siblings property wrapper
final class User: Model, Content {
    static let schema = "users"

    @ID(key: .id)
    var id: UUID?

    @Siblings(through: Relations.RelatedTags.through, from: \.$from, to: \.$to)
    var relatedTags: [Tag]
}
  1. Add initial migration for pivot Fluent model representing the sibling after related models:
private func configureDatabaseInitialMigrations(_ app: Application) {
    app.migrations.add(Todo.createInitialMigration())
    app.migrations.add(Tag.createInitialMigration()) 
    app.migrations.add(Todo.Relations.RelatedTags.Through.createInitialMigration())
}
  1. Profit! No need to feel pain from pivot models manual creation any more.