蒸气4:不急于加载儿童关系,请使用$前缀访问

问题描述

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

我有函数Type 3,当用主体调用URL addToParty时会被调用

/party/join/:partyID

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

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

当我尝试上面的代码时,我从行中收到错误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),is_ready: input.is_ready)) element.$users,但是它抱怨无法在范围内找到$Userelement.$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
    }
}

任何帮助将不胜感激。 预先谢谢你。

解决方法

不幸的是,将子级添加到父级模型还不是一个主动。我希望有一天我们可以添加它,但是还不存在。也许流利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),partyID: element.id
        ).save(on: req.db)
    }.transform(to: Party.Output(code: "200"))
}