给定一个控制器方法,它接受符合Vapor中实体中某些或所有属性的请求体,是否有更新实体的方法而无需手动分配所有属性?目前,我必须这样做:
func update(_ req: Request) throws -> Future<Mission> {
let mission = try req.parameters.next(Mission.self)
let content = try req.content.decode(Mission.self)
return flatMap(to: Mission.self, mission, content) { (mission, content) in
mission.propertyA = content.propertyA
mission.propB = content.propB
mission.propC = content.propC
return mission.save(on: req)
}
}
这不是很可扩展,因为它需要我手动分配每个属性。我正在寻找的是这样的:
func update(_ req: Request) throws -> Future<Mission> {
let mission = try req.parameters.next(Mission.self)
let content = try req.content.decode(Mission.self)
return mission.save(on: content)
}
然而,这会产生错误Argument type 'EventLoopFuture<Mission>' does not conform to expected type 'DatabaseConnectable'
。
这里有什么好的解决方案?
使用Submissions你应该能够做到:
func create(req: Request) throws -> Future<Either<Mission, SubmissionValidationError>> {
return try req.content.decode(Mission.Submission.self)
.updateValid(on: req)
.save(on: req)
.promoteErrors()
}
它需要一些设置,但它很灵活,允许您验证您的输入。结果中的promoteErrors
函数+ Either
有助于创建有用的错误响应,但您可以不使用它们。
您收到的错误是因为您尝试保存(on:content),您需要保存请求:
return mission.save(on: req)
话虽这么说,你真正想要的是这个:
func update(_ req: Request) throws -> Future<Mission> {
let updatedMission = try req.content.decode(Mission.self)
return updatedMission.update(on: req)
}
这将解码请求正文中的Mission对象,然后使用数据库中的相应ID更新Mission。因此,请确保当您在身体中发送具有ID的Mission JSON时。