更新模型的简捷方法以与Swift匹配请求正文?

时间:2018-08-30 00:00:07

标签: swift vapor

给定一个控制器方法,该方法接受一个符合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'

这里有什么好的解决方案?

2 个答案:

答案 0 :(得分:1)

使用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可帮助创建有用的错误响应,但是您可以不用它们。

答案 1 :(得分:1)

您收到的错误是因为您要保存(内容),需要保存请求:

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。因此,请确保在正文中发送Mission JSON时具有ID。