【问题标题】:Serverside Swift and Vapor on UbuntuUbuntu 上的服务器端 Swift 和 Vapor
【发布时间】:2020-04-08 13:55:05
【问题描述】:

我正在尝试通过 Paul Hudson 从 Server Side Swift 编写基于 Project2 的 API https://www.hackingwithswift.com/store/server-side-swift

我正在跑步:

Swift 5.0 版 (swift-5.0-RELEASE) 目标:x86_64-unknown-linux-gnu

蒸汽工具箱: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...
}

tenureTypepropertyType 被定义为String? 时,一切正常,但我认为使用枚举来指定tenureTypepropertyType 的可能值很有用。

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

问题是,当我尝试对 tenureTypepropertyType 使用枚举时,应用程序构建得很好,但是当我运行蒸汽服务器时,我得到了这个错误。

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$

当我将 tenureTypepropertyType 指定为可选(我认为它们应该是)时,错误值为 1 - 当它们不是可选时,错误值为 0。

我应该补充一点,这个错误只发生在我第一次运行服务器时,即:当它创建(空)数据库时。如果我第一次使用 tenureTypepropertyType 定义为 String? 运行它,它运行正常,然后我可以将它们更改为枚举,它继续正常工作。

【问题讨论】:

    标签: swift sqlite server enums vapor


    【解决方案1】:

    您需要使您的enum 符合SQLiteEnumTypeReflectionDecodable。您还需要为每种情况提供字符串值。以您的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...
    }
    

    【讨论】:

    • 谢谢@Nick。尝试过并得到redundant conformance of 'TenureType' to protocol 'Decodable'EncodableReflectionDecodable - 如果我把它拿出来,我会留下SQLiteEnumType 并且它会构建但是当我运行它时又回到原来的错误。 :-|
    • 取出 ReflectionDecodable 并将 Codable 更改为 Content 解决了 redundant conformance 问题 - 完美运行 - 谢谢。
    猜你喜欢
    • 2019-08-02
    • 1970-01-01
    • 2019-09-20
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 2017-08-04
    • 2019-09-18
    • 1970-01-01
    相关资源
    最近更新 更多