Model

public protocol Model : Reflectable, AnyModel

Represents a single table / collection in a Fluent database. Models are the basis for querying databases (create, read, update, and delete).

Models can also conform to Migration to provide prepare and revert methods for performing actions on the database before the application boots.

Both structs and classes can be models. Since Fluent is closure-based, copied structs will be returned by any methods that must mutate the model.

Here is an example of a simple User model.

final class User: Model {
    typealias Database = PostgreSQLDatabase
    static let idKey: WritableKeyPath<User, UUID?> = \.id
    var id: UUID?
    var name: String

    init(id: UUID? = nil, name: String) {
        self.id = id
        self.name = name
    }
}

Most of the time, you should use the Fluent driver’s sub-protocols for conforming to Model instead of using the protocol directly.

Query

To create a QueryBuilder for a model, use the query(on:) method.

let users = try User.query(on: req).filter(\.name == "Vapor").all()

You can also create QueryBuilders for any Decodable type. However, QueryBuilders created for Models have some extra methods and functionality.

Lifecycle

Models can implement optional lifecycle methods to hook into Fluent actions.

final class User: Model {
    ...
    func willDelete(on conn: PostgreSQLConnection) throws -> Future<User> {
        print("Deleting user: \(id)")
        return conn.future(self)
    }
}

Timestamps

Models are capable of storing timestamps representing when this model was first created and when it was last updated. If you decide to store timestamps on your model, Fluent will automatically update them whenever changes to the database are made.

final class User: Model {
    static let createdAtKey: TimestampKey? = \User.createdAt
    static let updatedAtKey: TimestampKey? = \User.updatedAt
    ...
    var createdAt: Date?
    var updatedAt: Date?
}

Add timestamp keys pointing to the properties on your model to let Fluent automatically update the values. You can set key paths for one or both of the keys per model.

Soft Delete

Instead of actually deleting rows from the database, soft deleted models can have a deleted at property set.

final class User: Model {
    ...
    var deletedAt: Date?
}

extension User: SoftDeletable {
    static let deletedAtKey: TimestampKey? = \.deletedAt
}

You can add SoftDeletable to existing models that have an optional Date property for storing the deleted at date.

Note

The deleted at date may be set in the future. The model will continue to be included in queries until the deleted at date passes.

Use softDelete(on:) to soft-delete a SoftDeletable model from the database. Use restore(on:) to restore a soft-deleted model.

let user: User
try user.softDelete(on: conn)
// later ...
try user.restore(on: conn)

Use excludeSoftDeleted() on QueryBuilder to exclude soft-deleted results (included by default).

User.query(on: conn).excludeSoftDeleted().count()

SoftDeletable models have extra lifecycle events:

- `willRestore`.
- `didRestore`.
- `willSoftDelete`.
- `didSoftDelete`.

See Model to learn more about Fluent lifecycle hooks.

  • ID

    The associated Identifier type. Usually Int or UUID. Must conform to ID.

    Declaration

    Swift

    associatedtype ID : ID
  • Typealias for Swift KeyPath to an optional ID for this model.

    Declaration

    Swift

    typealias IDKey = WritableKeyPath<Self, ID?>
  • Swift KeyPath to this Model‘s identifier.

    Declaration

    Swift

    static var idKey: IDKey { get }
  • Timestamp key.

    Declaration

    Swift

    typealias TimestampKey = WritableKeyPath<Self, Date?>
  • createdAtKey Default implementation

    The date at which this model was created. nil if the model has not been created yet. By default, Fluent will assume your model does not have a created at key.

    Default Implementation

    See Model.

    Declaration

    Swift

    static var createdAtKey: TimestampKey? { get }
  • updatedAtKey Default implementation

    The date at which this model was last updated. nil if the model has not been created yet. By default, Fluent will assume your model does not have an updated at key.

    Default Implementation

    See Model.

    Declaration

    Swift

    static var updatedAtKey: TimestampKey? { get }
  • deletedAtKey Default implementation

    The date at which this model was or will be soft deleted. nil if the model has not been deleted yet. If this property is set, the model will not be included in any query results unless withSoftDeleted() is used on the QueryBuilder.

    Default Implementation

    See Model.

    Declaration

    Swift

    static var deletedAtKey: TimestampKey? { get }
  • willCreate(on:) Default implementation

    Called before a model is created when saving.

    Note

    Throwing will cancel the save.

    Default Implementation

    See Model.

    Declaration

    Swift

    func willCreate(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • didCreate(on:) Default implementation

    Called after the model is created when saving.

    Default Implementation

    See Model.

    Declaration

    Swift

    func didCreate(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • willRead(on:) Default implementation

    Called before a model is fetched.

    Note

    Throwing will cancel the fetch.

    Default Implementation

    See Model.

    Declaration

    Swift

    func willRead(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • willUpdate(on:) Default implementation

    Called before a model is updated when saving.

    Note

    Throwing will cancel the save.

    Default Implementation

    See Model.

    Declaration

    Swift

    func willUpdate(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • didUpdate(on:) Default implementation

    Called after the model is updated when saving.

    Default Implementation

    See Model.

    Declaration

    Swift

    func didUpdate(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • willDelete(on:) Default implementation

    Called before a model is deleted.

    Note

    Throwing will cancel the delete.

    Default Implementation

    See Model.

    Declaration

    Swift

    func willDelete(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • didDelete(on:) Default implementation

    Called after the model is deleted.

    Default Implementation

    See Model.

    Declaration

    Swift

    func didDelete(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • willRestore(on:) Default implementation

    Called before a model is restored (from being soft deleted).

    Note

    Throwing will cancel the restore.

    Default Implementation

    See Model.

    Declaration

    Swift

    func willRestore(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • didRestore(on:) Default implementation

    Called after the model is restored (from being soft deleted.

    Default Implementation

    See Model.

    Declaration

    Swift

    func didRestore(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • willSoftDelete(on:) Default implementation

    Called before a model is soft deleted.

    Note

    Throwing will cancel the soft delete.

    Default Implementation

    See Model.

    Declaration

    Swift

    func willSoftDelete(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • didSoftDelete(on:) Default implementation

    Called after the model is soft deleted.

    Default Implementation

    See Model.

    Declaration

    Swift

    func didSoftDelete(on conn: Database.Connection) throws -> Future<Self>

    Parameters

    conn

    Current database connection.

  • addProperties(to:) Extension method

    Automatically adds SchemaFields for each of this Models properties.

    PostgreSQLDatabase.create(User.self, on: conn) { builder in
        try User.addProperties(to: builder)
        // use the builder to add other things like indexes
    }
    

    This method will be used automatically by Model‘s default conformance to Migration.

    Declaration

    Swift

    public static func addProperties(to builder: SchemaCreator<Self>) throws

    Parameters

    builder

    SchemaCreator to add the properties to.

  • save(on:) Extension method

    Saves the model, calling either create(...) or update(...) depending on whether the model already has an ID.

    If you need to create a model with a pre-existing ID, call create instead.

    let user = User(...)
    user.save(on: req)
    

    Declaration

    Swift

    public func save(on conn: DatabaseConnectable) -> Future<Self>

    Parameters

    conn

    Database connection to use.

    Return Value

    Future containing the saved model.

  • create(on:) Extension method

    Saves this model as a new item in the database. This method can auto-generate an ID depending on ID type.

    let user = User(...)
    user.create(on: req)
    

    Declaration

    Swift

    public func create(on conn: DatabaseConnectable) -> Future<Self>

    Parameters

    conn

    Database connection to use.

    Return Value

    Future containing the created model.

  • update(on:originalID:) Extension method

    Updates the model. This requires that the model has its ID set.

    user.update(on: req, originalID: 42)
    

    Declaration

    Swift

    public func update(on conn: DatabaseConnectable, originalID: ID? = nil) -> Future<Self>

    Parameters

    conn

    Database connection to use.

    originalID

    Specify the original ID if the ID has changed.

    Return Value

    Future containing the updated model.

  • delete(force:on:) Extension method

    Deletes this model from the database. This requires that the model has its ID set.

    user.delete(on: req)
    

    Declaration

    Swift

    public func delete(force: Bool = false, on conn: DatabaseConnectable) -> Future<Void>

    Parameters

    force

    If true, the model will be deleted from the database even if it has a deletedAtKey. This is false by default.

    conn

    Database connection to use.

    Return Value

    Future that will be completed when the delete is done.

  • restore(on:) Extension method

    Restores a soft deleted model.

    user.restore(on: req)
    

    Declaration

    Swift

    public func restore(on conn: DatabaseConnectable) -> Future<Self>

    Parameters

    conn

    Used to fetch a database connection.

    Return Value

    A future that will return the succesfully restored model.

  • query(on:withSoftDeleted:) Extension method

    Creates a query for this model type on the supplied connection.

    let users = try User.query(on: req).filter(\.name == "Vapor").all()
    

    Declaration

    Swift

    public static func query(on conn: DatabaseConnectable, withSoftDeleted: Bool = false) -> QueryBuilder<Self.Database, Self>

    Parameters

    conn

    Something DatabaseConnectable to create the QueryBuilder on.

    withSoftDeleted

    If true, soft-deleted models will be included in the results. Defaults to false.

    Return Value

    A new QueryBuilder for this model.

  • find(_:on:) Extension method

    Attempts to find an instance of this model with the supplied identifier.

    let user = try User.find(42)
    

    Declaration

    Swift

    public static func find(_ id: Self.ID, on conn: DatabaseConnectable) -> Future<Self?>

    Parameters

    id

    ID to lookup.

    conn

    Something DatabaseConnectable to create the QueryBuilder on.

    Return Value

    A future containing the model, if found.

  • defaultDatabase Extension method

    This Model’s default database. This will be used when no database id is passed (for example, on Model.query(on:)) or when it is not possible to pass a database (such as static lookup).

    You can set this property manually for each model. This is especially useful if you are not using migrations.

    User.defaultDatabase = .mysql
    

    Make sure to set this property before running any queries using your model.

    Declaration

    Swift

    public static var defaultDatabase: DatabaseIdentifier<Database>? { get set }
  • requireDefaultDatabase() Extension method

    Returns the defaultDatabase or throws an error.

    Declaration

    Swift

    public static func requireDefaultDatabase() throws -> DatabaseIdentifier<Database>
  • make(for:using:) Extension method

    See Parameter.

    Declaration

    Swift

    public static func make(for parameter: String, using container: Container) throws -> Future<Self>
  • resolveParameter(_:on:) Extension method

    See Parameter.

    Declaration

    Swift

    public static func resolveParameter(_ parameter: String, on container: Container) throws -> Future<Self>
  • children(_:) Extension method

    Create a children relation for this model.

    var pets: Children<User, Pet> {
        return children(\.userID)
    }
    

    The parentID should refer to the field on the child entity that contains the parent’s ID.

    Declaration

    Swift

    public func children<Child>(_ parentID: KeyPath<Child, Self.ID>) -> Children<Self, Child> where Child : Model, Self.Database == Child.Database
  • children(_:) Extension method

    Create a children relation for this model.

    var pets: Children<User, Pet> {
        return children(\.userID)
    }
    

    The parentID should refer to the field on the child entity that contains the parent’s ID.

    Declaration

    Swift

    public func children<Child>(_ parentID: KeyPath<Child, Self.ID?>) -> Children<Self, Child> where Child : Model, Self.Database == Child.Database
  • parent(_:) Extension method

    Create a children relation for this model.

    var user: Parent<User, Pet> {
        return parent(\.userID)
    }
    

    The parentID should refer to the field on the child entity that contains the parent’s ID.

    Declaration

    Swift

    public func parent<P>(_ parentID: KeyPath<Self, P.ID>) -> Parent<Self, P> where P : Model, Self.Database == P.Database
  • parent(_:) Extension method

    Create a children relation for this model.

    var user: Parent<Pet, User>? {
        return parent(\.userID)
    }
    

    This method supports an optional relation and will return nil if the parent ID is nil.

    The parentID should refer to the field on the child entity that contains the parent’s ID.

    Declaration

    Swift

    public func parent<P>(_ parentID: KeyPath<Self, P.ID?>) -> Parent<Self, P>? where P : Model, Self.Database == P.Database
  • Create a siblings relation for this model.

    Unless you are doing custom keys, you should not need to pass any parameters to this function.

    class Toy: Model {
        var pets: Siblings<Toy, Pet, PetToyPivot> {
            return siblings()
        }
    }
    

    See Siblings class documentation for more information about the many parameters. They can be confusing at first!

    Note

    From is assumed to be the model you are calling this method on.

    Declaration

    Swift

    public func siblings<Related, Through>(
        related: Related.Type = Related.self,
        through: Through.Type = Through.self,
        _ basePivotField: WritableKeyPath<Through, Self.ID>,
        _ relatedPivotField: WritableKeyPath<Through, Related.ID>
    ) -> Siblings<Self, Related, Through>
  • siblings(related:through:) Extension method

    Free implementation where pivot constraints are met. See Model.siblings(_:_:).

    Declaration

    Swift

    public func siblings<Related, Through>(
        related: Related.Type = Related.self,
        through: Through.Type = Through.self
    ) -> Siblings<Self, Related, Through>
        where Through.Right == Self, Through.Left == Related
  • siblings(related:through:) Extension method

    Free implementation where pivot constraints are met. See Model.siblings(_:_:).

    Declaration

    Swift

    public func siblings<Related, Through>(
        related: Related.Type = Related.self,
        through: Through.Type = Through.self
    ) -> Siblings<Self, Related, Through>
        where Through.Left == Self, Through.Right == Related