ruby-on-rails - migrations - rails references
Estructura de la base de datos para seguir el historial de cambios (6)
Estoy trabajando en diseños de bases de datos para un sistema de gestión de proyectos como proyecto personal y me he encontrado con un problema.
Quiero implementar un sistema de tickets y quiero que los tickets se vean como los tickets en Trac . ¿Qué estructura usaría para replicar este sistema? (No he tenido éxito instalando trac en ninguno de mis sistemas, así que realmente no puedo ver lo que está haciendo)
Nota: no me interesa intentar almacenar o mostrar el ticket en ninguna versión. Solo necesitaría un historial de cambios. No quiero almacenar datos adicionales. Además, he implementado una característica como esta usando una matriz serializada en un campo de texto. No quiero implementar eso como una solución nunca más.
Editar: estoy buscando solo estructuras de bases de datos. Los disparadores / devoluciones de llamada no son realmente un problema.
¿Estás buscando un mecanismo de base de datos como este?
CREATE OR REPLACE TRIGGER history$yourTable
BEFORE UPDATE ON yourTable
FOR EACH ROW
BEGIN
INSERT INTO
history
VALUES
(
:old.field1,
:old.field2,
:old.field3,
:old.field4,
:old.field5,
:old.field6
);
END;
/
SHOW ERRORS TRIGGER history$yourTable
Hice algo así. Tengo una tabla llamada LoggableEntity que contiene: ID (PK).
Luego tengo la tabla EntityLog que contiene información sobre los cambios realizados en una entidad de almacenamiento (registro): ID (PK), EntityID (FK a LoggableEntity.ID), ChangedBy (nombre de usuario que hizo un cambio), ChangedAt (smalldatetime cuando ocurrió el cambio), Escriba (enum: Crear, Eliminar, Actualizar), Detalles (el campo memo que contiene lo que ha cambiado - podría ser un XML con detalles serializados).
Ahora cada tabla (entidad) de la que quiero hacer un seguimiento se "deriva" de la tabla LoggableEntity, lo que significa que, por ejemplo, el Cliente tiene una tabla de FK a LoggableEntity.
Ahora mi código DAL se encarga de completar la tabla EntityLog cada vez que se realiza un cambio en un registro de cliente. Cada vez que ve que esa clase de entidad es una entidad de almacenamiento, agrega un nuevo registro de cambio en la tabla de registro de la entidad.
Así que aquí está la estructura de mi mesa:
+------------------+ +------------------+
| LoggableEntity | | EntityLog |
| ---------------- | | ---------------- |
| (PK) ID | <--+ | (PK) ID |
+------------------+ +----- | (FK) LoggableID |
^ | ... |
| +------------------+
+------------------+
| Customer |
| ---------------- |
| (PK) ID |
| (FK) LoggableID |
| ... |
+------------------+
Una posible solución es almacenar una copia del ticket en una tabla de historial con el usuario que realizó el cambio.
Sin embargo, esto almacenará una gran cantidad de datos adicionales y requerirá mucho procesamiento para crear la vista que muestra Trac.
Yo diría crear algún tipo de clase de escucha de eventos a la que haga ping cada vez que ocurra algo dentro de su sistema y coloque una descripción del evento en una base de datos.
Debe almacenar información básica de quién / qué / dónde / cuándo / qué.
ordenar la tabla de eventos de proyectos debería proporcionarle la información que desea.
Implementé datos puros de cambio de registro usando un diseño "delgado":
RecordID Table Column OldValue NewValue
-------- ----- ------ -------- --------
Puede que no desee utilizar "Tabla" y "Columna", sino más bien "Objeto" y "Propiedad", y demás, según su diseño.
Esto tiene la ventaja de la flexibilidad y la simplicidad, a costa de la velocidad de consultas: los índices agrupados en las columnas "Tabla" y "Columna" pueden acelerar las consultas y los filtros. Pero si va a ver el registro de cambios en línea con frecuencia a nivel de tabla o de objeto, es posible que desee diseñar algo más plano.
EDITAR : varias personas han señalado con razón que con esta solución no se podía establecer un conjunto de cambios. Olvidé esto en la tabla anterior: la implementación con la que trabajé también tenía una tabla de "Transacción" con fecha y hora, usuario y otra información, y una columna "ID de transacción", por lo que el diseño sería así:
CHANGE LOG TABLE:
RecordID Table Column OldValue NewValue TransactionID
-------- ----- ------ -------- -------- -------------
TRANSACTION LOG TABLE:
TransactionID UserID TransactionDate
------------- ------ ---------------
En cuanto a no almacenar una gran cantidad de datos adicionales, no puedo pensar en ninguna buena manera de hacerlo. Tienes que almacenar cada revisión para ver los cambios.
Aquí hay una solución que he visto, aunque no estoy seguro de si es la mejor. Tener una clave principal, dig id
que apunta a una revisión en particular. también tienen los campos ticket_number
y revision_date
. ticket_number
no cambia cuando ticket_number
un ticket, pero lo hacen id
y revision_date
. Luego, dependiendo del contexto, puede obtener una revisión particular, o la última revisión de un ticket en particular, utilizando groupwise max .