2

目前我正在做一个学校作业,我们必须使用 Vapor 构建一个 API。我有一些基本的 API 调用正在工作,我现在正在尝试一些更高级的 API 调用,但我无法让它工作。

当使用正文调用addToPartyURL 时,我有这个函数被调用/party/join/:partyID

{
    "id": "CC1FAC6B-A2B3-471C-A488-147300196981",
    "username": "string",
    "is_ready": true
}

我正在尝试通过partyId 找到一个聚会并将用户添加到聚会的用户列表中。

func addToParty (req: Request) throws -> EventLoopFuture<Party.Output> {
    guard let id = req.parameters.get("partyID", as: UUID.self) else {
        throw Abort(.badRequest)
    }
    let input = try req.content.decode(Party.JoinParty.self)
    return Party.find(id, on: req.db)
        .unwrap(or: Abort(.notFound))
        .flatMap { element in
        element.users.append(User(id: UUID(input.id), username: input.username, is_ready: input.is_ready))
        return element.save(on: req.db)
            .map{ Party.Output(code: "200") }
        }
    } 

当我尝试上面的代码时,我Fatal error: Children relation not eager loaded, use $ prefix to access: Children<Party, User>(for: [party_id]): file FluentKit/Children.swift, line 33从该行得到错误

element.users.append(User(id: UUID(input.id), username: input.username, is_ready: input.is_ready))

当我评论这一行时,代码运行,我得到一个返回码。

我尝试将前缀添加到element.$users$User但随后它抱怨无法找到element.$users$User在范围内。

Party model

import Fluent
import Vapor

final class Party: Model, Content {
    static let schema = "parties"

    struct JoinParty: Content {
        let id: String
        let username: String
        let is_ready: Bool
    }

    struct Output: Content {
        let code: String
    }
    
    @ID(key: .id)
    var id: UUID?

    @Field(key: "party_code")
    var party_code: String
    
    @Field(key: "host_id")
    var host_id: UUID

    @Field(key: "is_active")
    var is_active: Bool

    // change to Game when model is made
    @Field(key: "selected_games")
    var selected_games: [String]?

    // change to Setting when model is made  
    @Field(key: "settings")
    var settings: String

    @Field(key: "results")
    var results: Array<GameResult>?

    @Children(for: \.$party)
    var users: [User]

    init() { }

    init(id: UUID? = nil,
        party_code: String,
        host_id: UUID,
        is_active: Bool,
        selected_games: [String]? = nil,
        settings: String,
        results: Array<GameResult>? = nil) {
        self.id = id
        self.party_code = party_code
        self.host_id = host_id
        self.is_active = is_active
        self.selected_games = selected_games
        self.settings = settings
        self.results = results
    }
}

User model

import Fluent
import Vapor

final class User: Model, Content {
    static let schema = "users"

    struct Input: Content {
        let id: UUID
        let username: String
    }

    struct Output: Content {
        let id: String
        let username: String
    }
    
    @ID(key: .id)
    var id: UUID?

    @Field(key: "username")
    var username: String

    @Field(key: "is_ready")
    var is_ready: Bool

    @OptionalParent(key: "party_id")
    var party: Party?

    @Children(for: \.$user)
    var gameResults: [GameResult]

    init() {}

    init(id: UUID? = nil, username: String, is_ready: Bool, partyID: UUID? = nil) {
        self.id = id
        self.username = username
        self.is_ready = is_ready
        self.$party.id = partyID
    }
}

我有一个类似的功能来更新已经工作的用户的用户名,这几乎是一样的。

func update(req: Request) throws -> EventLoopFuture<User.Output> {
      let input = try req.content.decode(User.Input.self)
        return User.find(input.id, on: req.db)
            .unwrap(or: Abort(.notFound))
            .flatMap { user in
                user.username = input.username
                return user.save(on: req.db)
                    .map { User.Output(id: user.id!.uuidString, username: user.username) }
            }
      }

任何帮助将非常感激。先感谢您。

4

1 回答 1

3

不幸的是,将子模型添加到父模型还不是那么直观。我希望有一天我们可以添加它,但它还没有。流利5可以吗?

无论如何,您需要做的是创建新User模型,将当事方的 ID 值传递给partyID初始化参数,然后保存User模型。

let user = User(id: UUID(input.id), username: input.username, is_ready: input.is_ready, partyID: element.id)
return user.save(on: request.db)

所以你的方法最终应该是这样的:

func addToParty(req: Request) throws -> EventLoopFuture<Party.Output> {
    guard let id = req.parameters.get("partyID", as: UUID.self) else {
        throw Abort(.badRequest)
    }
    let input = try req.content.decode(Party.JoinParty.self)

    return Party.find(id, on: req.db).unwrap(or: Abort(.notFound)).flatMap { element in
        return User(
            id: UUID(input.id), 
            username: input.username, 
            is_ready: input.is_ready,
            partyID: element.id
        ).save(on: req.db)
    }.transform(to: Party.Output(code: "200"))
}
于 2020-10-20T14:00:15.193 回答