Erwartet:
Beim Erstellen der Spalte updated_ts
in table.timestamps()
sollte die DDL wie folgt lauten:
timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Tatsächlich:
Der Teil ON UPDATE CURRENT_TIMESTAMP
fehlt - die Spalte updated_ts
wird nie automatisch aktualisiert.
Die Syntax, die ich beschreibe, funktioniert für MySQL, ich bin mir nicht sicher, wie kompatibel sie mit Datenbank-Engines ist.
Zumindest bei Postgres ist die Syntax nicht ganz so schön:
http://stackoverflow.com/questions/1035980/update-timestamp-when-row-is-updated-in-postgresql
Obwohl ich die .autoUpdate()
Builder-Methode für die timestamp
Spalte haben möchte, wäre es trivial, dies auch für den .timestamps()
Helfer zu aktivieren.
Sieht so aus, als hätte SQLite3 auch Trigger, mit denen dies implementiert werden könnte. Oracle und mssql könnten auch eine schönere Syntax dafür haben oder zumindest mit Triggern gemacht werden.
Das wäre so schön! Derzeit müssen wir uns darauf verlassen, dass das Bücherregal unsere Zeitstempel aktualisiert, oder?
Anstatt sich auf ein Bücherregal zu verlassen, können Sie die Datetime-Felder manuell erstellen (mysql):
table.dateTime('created_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP'))
table.dateTime('updated_at').defaultTo(knex.raw('NULL ON UPDATE CURRENT_TIMESTAMP'))
Oder wenn Sie es vorziehen, dass updated_at
auch standardmäßig zur Erstellungszeit verwendet wird:
table.dateTime('created_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP'))
table.dateTime('updated_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
Anstatt sich auf ein Bücherregal zu verlassen, können Sie die Datetime-Felder manuell erstellen (mysql):
table.dateTime('created_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP')) table.dateTime('updated_at').defaultTo(knex.raw('NULL ON UPDATE CURRENT_TIMESTAMP'))
Wenn Sie den Code, den Sie für updated_at gepostet haben, mit null default verwenden, wird immer noch der aktuelle Zeitstempel für updated_at eingefügt.
const UserModel = bookshelf.Model.extend({
tableName: 'users',
hasTimestamps: ['createdAt', 'updatedAt'],
});
Dieser Test schlägt fehl:
it('doesntStoreUpdatedAtForCreation', async () => {
// arrange && act
const inserted = await new UserModel().save();
// assert
const retrievedModel = await UserModel.where({ id: inserted.id }).fetch();
assert.notExists(retrievedModel.get('updatedAt'));
});
Bearbeiten:
Egal, scheint das vollständige Entfernen von hasTimestamps
aus der Modelldefinition dies zu beheben.
Wir mischen hier Knex- und Bookshelf-Probleme, aber @Ice32, wenn Sie die automatische Zeitstempelfunktion von Bookshelf nicht verwenden möchten, müssen Sie hasTimestamps: ['createdAt', 'updatedAt']
aus Ihrer Modelldefinition entfernen. Der Code, den @codeclown oben gepostet hat,
Meine Lösung:
const Database = use("Database");
/*......*/
table
.timestamp("created_at")
.notNullable()
.defaultTo(Database.raw("CURRENT_TIMESTAMP"));
table
.timestamp("updated_at")
.notNullable()
.defaultTo(
Database.raw("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
);
Ich denke, timestamps()
muss entweder diese Auto-Update-Funktionalität bereitstellen oder die Dokumente müssen explizit angeben, dass dies nicht der Fall ist. Ich habe einfach angenommen, dass die Funktionalität ein entscheidender Grund dafür ist, warum die Methode timestamps()
existiert.
Die Methode timestamps()
ist für mich nutzlos, da on update current_timestamp
nicht gesetzt werden kann.
Hilfreichster Kommentar
Ich denke,
timestamps()
muss entweder diese Auto-Update-Funktionalität bereitstellen oder die Dokumente müssen explizit angeben, dass dies nicht der Fall ist. Ich habe einfach angenommen, dass die Funktionalität ein entscheidender Grund dafür ist, warum die Methodetimestamps()
existiert.