EncodableRecord

public protocol EncodableRecord

Types that adopt EncodableRecord can be encoded into the database.

  • 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.

    Declaration

    Swift

    func encode(to container: inout PersistenceContainer)

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

    Declaration

    Swift

    static var databaseEncodingUserInfo: [CodingUserInfoKey : Any] { get }
  • 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 (iOS 11.0+, macOS 10.13+, tvOS 11.0+, watchOS 4.0+)

    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

    Declaration

    Swift

    static func databaseJSONEncoder(for column: String) -> JSONEncoder
  • 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

    Declaration

    Swift

    static var databaseDateEncodingStrategy: DatabaseDateEncodingStrategy { get }
  • 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 = .string
    
        // encoded in a string like "E621E1F8-C36C-495A-93FC-0C247A3E6E5F"
        var uuid: UUID
    }
    

    Default Implementation

    Declaration

    Swift

    static var databaseUUIDEncodingStrategy: DatabaseUUIDEncodingStrategy { get }
  • 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: DatabaseUUIDEncodingStrategy = .convertToSnakeCase
    
        // encoded as player_id
        var playerID: String
    }
    

    Default Implementation

    Declaration

    Swift

    static var databaseColumnEncodingStrategy: DatabaseColumnEncodingStrategy { get }
  • databaseDictionary Extension method

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

    Declaration

    Swift

    public var databaseDictionary: [String : DatabaseValue] { get }

Record Comparison

  • databaseEquals(_:) Extension method

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

    Declaration

    Swift

    public func databaseEquals(_ record: Self) -> Bool
  • 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.

    Declaration

    Swift

    public func databaseChanges<Record>(from record: Record) -> [String : DatabaseValue] where Record : EncodableRecord