Серверные Swift и Vapor в Ubuntu

Я пытаюсь написать API на основе Project2 из Server Side Swift Пола Хадсона https://www.hackingwithswift.com/store/server-side-swift

Я бегаю:

Swift версии 5.0 (swift-5.0-RELEASE) Цель: x86_64-unknown-linux-gnu

а также

Панель инструментов Vapor: 3.1.10

на Ubuntu 18.04.3 LTS (GNU / Linux 4.15.0-66-generic x86_64)

Идея состоит в том, чтобы использовать Fluent и SQLite для ведения записей свойств (CRUD).

Соответствующая часть configure.swift:

let directoryConfig = DirectoryConfig.detect()
    services.register(directoryConfig)

    try services.register(FluentSQLiteProvider())

    var databaseConfig = DatabasesConfig()
    let db = try SQLiteDatabase(storage: .file(path: "\(directoryConfig.workDir)properties.db"))
    databaseConfig.add(database: db, as: .sqlite)
    services.register(databaseConfig)

    var migrationConfig = MigrationConfig()
    migrationConfig.add(model: Property.self, database: .sqlite)
    services.register(migrationConfig)

В Routes.swift у меня есть это:

    router.post(Property.self, at: "properties", "create") { req, property -> Future<Property> in
        return property.save(on: req)
    }

    router.get("properties", "list") { req -> Future<[Property]> in
        return Property.query(on: req).all()
    }

А Property.swift таков:

//  Property.swift
//
//  Created by Peter Matthews on 07/12/2019.
//

import Fluent
import FluentSQLite
import Foundation
import Vapor

enum TenureType: String, Codable {
    case freehold
    case cross_lease
    case unit_title
    //    etc...
}

enum PropertyType: String, Codable {
    case commercial
    case office
    case industrial
    case retail
    //    etc...
}

struct Property: Content, SQLiteUUIDModel, Migration {

    var id: UUID?
    var tenureType: TenureType?     //  var tenureType: String?
    var propertyType: PropertyType? //  var propertyType: String?
    //    etc...
}

Когда tenureType и propertyType определены как String?, все работает нормально, но я думаю, что есть веские основания для использования перечислений для указания возможных значений для tenureType и propertyType.

Terminal output:

pm@PHQ:~/PropertyHQ$ vapor run
Running PropertyHQ ...
[ INFO ] Migrating 'sqlite' database (/home/pm/PropertyHQ/.build/checkouts/fluent/Sources/Fluent/Migration/MigrationConfig.swift:69)
[ INFO ] Migrations complete (/home/pm/PropertyHQ/.build/checkouts/fluent/Sources/Fluent/Migration/MigrationConfig.swift:73)
Running default command: .build/debug/Run serve

Проблема в том, что когда я пытаюсь использовать перечисления для tenureType и propertyType, приложение строится нормально, но когда я запускаю паровой сервер, я получаю эту ошибку.

Terminal output:

pm@PHQ:~/PropertyHQ$ vapor run
Running PropertyHQ ...
[ INFO ] Migrating 'sqlite' database (/home/pm/PropertyHQ/.build/checkouts/fluent/Sources/Fluent/Migration/MigrationConfig.swift:69)
[ INFO ] Preparing migration 'Property' (/home/pm/PropertyHQ/.build/checkouts/fluent/Sources/Fluent/Migration/Migrations.swift:111)
⚠️ [DecodingError.dataCorrupted: Cannot initialize TenureType from invalid String value 1]
Error: Run failed.
pm@PHQ:~/PropertyHQ$

Когда я указываю tenureType и propertyType как необязательные (что, я думаю, они должны быть), значение ошибки равно 1 - когда они не являются необязательными, значение ошибки равно 0.

Я должен добавить, что эта ошибка возникает только тогда, когда я запускаю сервер в первый раз, то есть: когда он создает (пустую) базу данных. Если я запускаю его в первый раз с tenureType и propertyType, определенными как String?, он работает нормально, а затем я могу изменить их на перечисления, и он продолжает работать нормально.


person toberblue    schedule 16.12.2019    source источник


Ответы (1)


Вам необходимо согласовать ваш enum с SQLiteEnumType и ReflectionDecodable. Вам также необходимо указать строковые значения для каждого случая. Используя свой TenureType в качестве примера, попробуйте:

enum TenureType: String, Codable, SQLiteEnumType, ReflectionDecodable {
    static func reflectDecoded() throws -> (TenureType, TenureType) {
        return ( .freehold, .cross_lease )
    }
    case freehold = "freehold"
    case cross_lease = "cross_lease"
    case unit_title = "unit_title"
    //    etc...
}
person Nick    schedule 16.12.2019
comment
Спасибо, @Nick. Пытался получить redundant conformance of 'TenureType' to protocol 'Decodable', Encodable и ReflectionDecodable - если я вытащу это, у меня останется SQLiteEnumType, и он будет построен, но при запуске вернусь к исходной ошибке. : - | - person toberblue; 17.12.2019
comment
Вынул ReflectionDecodable и изменил Codable на Content, который устранил redundant conformance проблемы - отлично работает - спасибо. - person toberblue; 17.12.2019