Esperado:
Ao criar a coluna updated_ts
em table.timestamps()
, seu DDL deve ser:
timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Real:
A parte ON UPDATE CURRENT_TIMESTAMP
está faltando - a coluna updated_ts
nunca é atualizada automaticamente.
A sintaxe que estou descrevendo funciona para o MySQL, não tenho certeza de quão compatível é entre mecanismos de banco de dados.
Pelo menos com a sintaxe do postgres não é exatamente tão legal:
http://stackoverflow.com/questions/1035980/update-timestamp-when-row-is-updated-in-postgresql
Embora eu gostaria de ter o método .autoUpdate()
builder para a coluna timestamp
, seria trivial habilitá-lo para .timestamps()
helper também.
Parece que o SQLite3 também tem gatilhos que podem ser usados para implementar isso. Oracle e mssql também podem ter uma sintaxe mais agradável para ele ou pelo menos poderia ser feito com triggers.
Isso seria tão bom! atualmente, precisamos depender da estante de livros para atualizar nossos carimbos de data / hora, certo?
Em vez de confiar na estante de livros, você pode criar os campos de data e hora manualmente (mysql):
table.dateTime('created_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP'))
table.dateTime('updated_at').defaultTo(knex.raw('NULL ON UPDATE CURRENT_TIMESTAMP'))
Ou se você preferir updated_at
como padrão para a hora de criação também:
table.dateTime('created_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP'))
table.dateTime('updated_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
Em vez de confiar na estante de livros, você pode criar os campos de data e hora manualmente (mysql):
table.dateTime('created_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP')) table.dateTime('updated_at').defaultTo(knex.raw('NULL ON UPDATE CURRENT_TIMESTAMP'))
Usar o código que você postou para updated_at com default null ainda insere o carimbo de data / hora atual para updated_at.
const UserModel = bookshelf.Model.extend({
tableName: 'users',
hasTimestamps: ['createdAt', 'updatedAt'],
});
Este teste falha:
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'));
});
Editar:
Esqueça, parece que remover completamente hasTimestamps
da definição do modelo corrige isso.
Estamos misturando problemas de Knex e Bookshelf aqui, mas @ Ice32 se você não quiser usar o recurso de carimbo de data / hora automático do Bookshelf, você deve remover hasTimestamps: ['createdAt', 'updatedAt']
de sua definição de modelo. O código que @codeclown postou acima funcionará conforme o esperado.
Minha solução:
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")
);
Acho que timestamps()
precisa fornecer essa funcionalidade de atualização automática ou os documentos precisam declarar explicitamente que não. Eu simplesmente presumi que a funcionalidade era uma razão crítica para a existência do método timestamps()
.
O método timestamps()
é inútil para mim porque não pode definir on update current_timestamp
.
Comentários muito úteis
Acho que
timestamps()
precisa fornecer essa funcionalidade de atualização automática ou os documentos precisam declarar explicitamente que não. Eu simplesmente presumi que a funcionalidade era uma razão crítica para a existência do métodotimestamps()
.