EncodableRecord

Types that adopt EncodableRecord can be encoded into the database.

  • encode(to:) Default implementation

    Encodes the record into database values.

    Store in the container argument all values that should be stored in the columns of the database table (see databaseTableName()).

    Primary key columns, if any, must be included.

    struct Player: EncodableRecord {
        var id: Int64?
        var name: String?
    
        func encode(to container: inout PersistenceContainer) {
            container["id"] = id
            container["name"] = name
        }
    }
    

    It is undefined behavior to set different values for the same column. Column names are case insensitive, so defining both “name” and “NAME” is considered undefined behavior.

    Throws

    An error is thrown if the record can’t be encoded to its database representation.

    Default Implementation

Customizing the Format of Database Columns

  • databaseEncodingUserInfo Default implementation

    When the EncodableRecord type also adopts the standard Encodable protocol, you can use this dictionary to customize the encoding process into database rows.

    For example:

    // A key that holds a encoder's name
    let encoderName = CodingUserInfoKey(rawValue: "encoderName")!
    
    struct Player: PersistableRecord, Encodable {
        // Customize the encoder name when encoding a database row
        static let databaseEncodingUserInfo: [CodingUserInfoKey: Any] = [encoderName: "Database"]
    
        func encode(to encoder: Encoder) throws {
            // Print the encoder name
            print(encoder.userInfo[encoderName])
            ...
        }
    }
    
    let player = Player(...)
    
    // prints "Database"
    try player.insert(db)
    
    // prints "JSON"
    let encoder = JSONEncoder()
    encoder.userInfo = [encoderName: "JSON"]
    let data = try encoder.encode(player)
    

    Default Implementation

  • databaseJSONEncoder(for:) Default implementation

    When the EncodableRecord type also adopts the standard Encodable protocol, this method controls the encoding process of nested properties into JSON database columns.

    The default implementation returns a JSONEncoder with the following properties:

    • dataEncodingStrategy: .base64
    • dateEncodingStrategy: .millisecondsSince1970
    • nonConformingFloatEncodingStrategy: .throw
    • outputFormatting: .sortedKeys

    You can override those defaults:

    struct Achievement: Encodable {
        var name: String
        var date: Date
    }
    
    struct Player: Encodable, PersistableRecord {
        // stored in a JSON column
        var achievements: [Achievement]
    
        static func databaseJSONEncoder(for column: String) -> JSONEncoder {
            let encoder = JSONEncoder()
            encoder.dateEncodingStrategy = .iso8601
            return encoder
        }
    }
    

    Default Implementation

  • databaseDateEncodingStrategy Default implementation

    When the EncodableRecord type also adopts the standard Encodable protocol, this property controls the encoding of date properties.

    Default value is .deferredToDate

    For example:

    struct Player: PersistableRecord, Encodable {
        static let databaseDateEncodingStrategy: DatabaseDateEncodingStrategy = .timeIntervalSince1970
    
        var name: String
        var registrationDate: Date // encoded as an epoch timestamp
    }
    

    Default Implementation

  • databaseUUIDEncodingStrategy Default implementation

    When the EncodableRecord type also adopts the standard Encodable protocol, this property controls the encoding of UUID properties.

    Default value is .deferredToUUID

    For example:

    struct Player: PersistableProtocol, Encodable {
        static let databaseUUIDEncodingStrategy: DatabaseUUIDEncodingStrategy = .uppercaseString
    
        // encoded in a string like "E621E1F8-C36C-495A-93FC-0C247A3E6E5F"
        var uuid: UUID
    }
    

    Default Implementation

  • databaseColumnEncodingStrategy Default implementation

    When the EncodableRecord type also adopts the standard Encodable protocol, this property controls the key encoding strategy.

    Default value is .useDefaultKeys

    For example:

    struct Player: PersistableProtocol, Encodable {
        static let databaseColumnEncodingStrategy: DatabaseColumnEncodingStrategy = .convertToSnakeCase
    
        // encoded as player_id
        var playerID: String
    }
    

    Default Implementation

  • databaseDictionary Extension method

    A dictionary whose keys are the columns encoded in the encode(to:) method.

    Throws

    An error is thrown if the record can’t be encoded to its database representation.

Record Comparison

  • databaseEquals(_:) Extension method

    Returns a boolean indicating whether this record and the other record have the same database representation.

  • databaseChanges(from:) Extension method

    A dictionary of values changed from the other record.

    Its keys are column names. Its values come from the other record.

    Note that this method is not symmetrical, not only in terms of values, but also in terms of columns. When the two records don’t define the same set of columns in their encode(to:) method, only the columns defined by the receiver record are considered.

    Throws

    An error is thrown if one record can’t be encoded to its database representation.