Attività di progettazione / registrazione degli eventi (es: aggiornamento dei campi) in RDBMS

2

Sto cercando di implementare un sistema di tracciamento delle attività in Ruby on Rails per un'applicazione solo API.

Ho una tabella denominata letter con informazioni come segue:

  • id (chiave primaria)
  • sender_id (foreign_key su contact )
  • receiver_id (foreign_key su user )
  • owner_id (foreign_key su user )
  • re (stringa)
  • status (enum {ON_HOLD, CLOSED, OPENED})

Ogni volta che viene eseguito un aggiornamento (modifica titolo, proprietà o stato) voglio registrarlo in una tabella delle attività che verrà visualizzata accanto alla lettera sull'applicazione.

Si dovrebbe essere simile a problemi GitHub , dove possiamo vedere chi ha fatto cosa. Essere in grado di fare riferimento agli utenti, collegarsi al loro profilo, dice che qualcuno cambia il titolo da "qualcosa" a "un'altra cosa", ecc.

La cosa che voglio registrare ha un layout di informazioni diverso:

  • trasferire le modifiche: da, a (entrambi dovrebbero essere foreign_key)
  • modifiche ai metadati: nome_campo, valore_varia, valore_nuovo (stringhe)
  • cambiamenti di stato: old_status, new_status (enum)

Tutte queste tabelle hanno ID, autore delle modifiche, data di creazione.

Mi chiedo quale sarebbe il migliore per tenere traccia di questi cambiamenti.

Prima idea

Ho iniziato a creare una tabella activity come segue:

  • id (chiave primaria)
  • letter_id (foreign_key su letter )
  • created_at (datetime)
  • user_id (foreign_key su user )
  • type (enum {STATUS, TRANSFER, METADATA})
  • activity_id (numero intero che punta sull'id della tabella)

E creato una tabella per ogni voce enum nella colonna type e caricale manualmente usando activity_id . Ma l'ho trovato piuttosto brutto perché:

  • Non posso usare correttamente i join
  • disturba le capacità di Rails ORM
  • Dai, sono abbastanza sicuro che sia il modo sbagliato per RDBMS (no?)

Vorrei finire con questo tipo di codice:

activity = Activity.find(1)
if (activity.type == "STATUS")
  StatusActivity.find(activity.activity_id)
elsif (activity.type == "TRANSFER")
  TransferActivity.find(activity.activity_id)
...

Seconda idea

Basato sul layout activity della prima idea, invece di avere sulla colonna con l'ho pensato di avere altre colonne nullable in possesso di una foreign_key verso ogni tabella di voci enum:

  • id (chiave primaria)
  • letter_id (foreign_key su letter )
  • created_at (datetime)
  • user_id (foreign_key su user )
  • type (enum {STATUS, TRANSFER, METADATA})
  • status_activity_id
  • transfer_activity_id
  • metadata_activity_id

Non sembra fantastico; se voglio aggiungere un nuovo tipo di evento di attività, dovrò creare una colonna in più per ogni riga ...

Si finirebbe con questo tipo di codice:

activity = Activity.find(1)
if (activity.type == "STATUS")
  activity.status_activity
elsif (activity.type == "TRANSFER")
  activity.transfer_activity
...

Terza idea

Crea 3 diverse tabelle: status_activity , transfer_activity e metadata_activity . Interrogali separatamente, ordinali per data di creazione prima di serializzarli in JSON.

Nonostante tutte queste idee, non riesco a capire cosa sarebbe bello? Quindi hai qualche idea o consiglio?

    
posta Valentin Trinqué 09.12.2015 - 21:41
fonte

1 risposta

1

Un modo semplice per farlo è creare una nuova tabella chiamata history che ha un id , un date , forse anche un user_id per sapere chi ha fatto ogni modifica, e quindi semplicemente un string che contiene testo JSON che spiega cosa è successo. L'idea è che non utilizzerai realmente i campi storici nelle relazioni, probabilmente nemmeno nelle query, quindi non devono essere campi reali.

Un altro (piuttosto dispendioso ma completamente relazionale) modo di farlo è sostituire la tua tabella letter con una tabella letter_history , dove mantieni tutti i campi di table più un date e forse anche un user_id , quindi non modifichi mai alcuna riga esistente, aggiungi solo nuove righe con la data corrente e l'utente che ha apportato la modifica. Quindi, crei una vista chiamata letter che seleziona semplicemente la versione più recente di ogni lettera.

    
risposta data 09.12.2015 - 22:15
fonte

Leggi altre domande sui tag