问题描述
当前,我正在做一个学校作业,我们必须使用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
,但是它抱怨无法在范围内找到$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
}
}
任何帮助将不胜感激。 预先谢谢你。
解决方法
不幸的是,将子级添加到父级模型还不是一个主动。我希望有一天我们可以添加它,但是还不存在。也许流利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"))
}