У меня есть приложение Vapor, где я хочу, чтобы некоторые значения были указаны пользователем в запросе POST, а другие значения были вычислены на основе указанных пользователем значений.

Например, предположим, что пользователь исправляет некоторые новые значения, и каждый раз, когда это происходит, таблица должна автоматически обновлять столбец с текущим временем.

Я пытался сохранить вычисленные свойства в базе данных, но когда я изменил модель, чтобы узнать о вычисляемых свойствах, все мои запросы POST начали ожидать, что они будут указаны.

Какой самый идиоматичный способ иметь столбцы в таблице, которые не нужно указывать в почтовых запросах?

1
Barry Jones 19 Авг 2019 в 00:00

2 ответа

Лучший ответ

Если вы хотите обновить только измененную или созданную временную метку, есть два других способа. В вашей модели вставьте:

static let createdAtKey: TimestampKey? = \.createdAt
static let updatedAtKey: TimestampKey? = \.updatedAt
var createdAt:Date?
var updatedAt:Date?

И пусть Pour сделает это за вас, смотрите здесь . Кроме того, вы можете использовать методы willCreate, willUpdate и т. Д., Как описано в документации здесь, если вы обновляете поля, не требующие ввода данных пользователем.

extension User
{
    func willUpdate(on connection: Database.Connection) throws -> Future<User>
    {
        modifiedCount += 1
        return Future.map(on: connection) { self }
    }
}

Наконец, если вам нужно немного больше гибкости, чем собственное решение, подумайте об использовании этого в вашем контроллере:

struct EditUserForm:Content
{
    let id:Int
    let surname:String
    let initials:String
}

func save(_ request:Request) throws -> Future<View>
{
    return try request.content.decode(EditUserForm.self).flatMap
    {
        newUserData in
        return try request.parameters.next(User.self).flatMap
        {
            originalUser in
            // update fields as required, EditUserForm only has a subset
            return originalUser.save(on:request).transform(to:try self.index(request))
        }
    }
}

Вам понадобится обычный маршрут:

router.post(User.parameter, "save", use:userController.save)
2
Nick 19 Авг 2019 в 07:55

Я обнаружил, что мне нужно сделать вычисляемые поля необязательными в модели, а затем вычислить их в функции маршрута перед сохранением.

Например:

Делать modified_date необязательным в модели:

final class MyContentType: PostgreSQLModel {
    var id: Int?
    var name: String
    var modified_date: Date?
}

Установка modified_date в вычисленное значение:

    func create(_ request: Request, content: MyContentType) throws -> Future< MyContentType > {
        content.modified_date = Date()
        return content.save(on: request)
    }
1
Barry Jones 19 Авг 2019 в 03:14