Ereditarietà di una tabella singola e dove utilizzarla in Rails

Sono bloccato in un problema di design strano,

Sto lavorando a due tipi di profili Modelli,

  • Profilo utente (appartiene all’utente)
  • altri che mantengono sul posto come “bot” (non appartiene a nessuno)

Il tipico comportamento OO di questi due tipi di Profili è lo stesso, ma solo gli attributi / proprietà importanti sono comuni (quelli molto importanti 5-6 in numero), altre proprietà come “interessi ecc.” (Quasi 10-15 proprietà) non ci sono per i profili bot

Il programmatore che ha lavorato a questo progetto ha creato modelli / controllori separati per profili di bot / profili utente che creano molta ridondanza ovunque e anche come ci si aspettava difficile da mantenere, scrivere test, ecc. Ho voluto ASCIUGARLA, almeno per risolvere alcuni / tutti di questi problemi di ridondanza.

Qualcuno ha suggerito l’ereditarietà di una tabella singola come soluzione

Qualcuno ha suggerito invece di utilizzare le associazioni polimorfiche.

qual è l’approccio migliore Quando usiamo effettivamente STI?

Il mio pensiero è che STI è usato al meglio quando gli attributi sono gli stessi per i modelli e differiscono nel comportamento.

Pensieri su cosa posso fare?

La caratterizzazione di STI è utile soprattutto quando gli attributi sono gli stessi, ma il comportamento differisce da “a destra”, ma forse un po ‘limitante. Mi piace usare STI quando esiste, come suggerisce il nome, una chiara relazione di ereditarietà stile OO, piuttosto che la relazione in stile database tra oggetti di tipi diversi.

Se c’è un codice comune tra bot e utenti, direi che STI sembra un vincitore. Se ci sono solo alcuni attributi comuni, probabilmente è meno applicabile ma vale comunque la pena provarci.

Sono una persona piuttosto sperimentale, quindi la mia raccomandazione è di provarla. Separa il tuo codice e rifatta i modelli in una relazione STI. Guarda se fa veramente asciugare le cose, o semplicemente scambia una serie di mal di testa per qualche altro problema.

Una cosa che penso non vedrai molto vantaggio è l’esaurimento dei controller. Nella mia esperienza, i modelli STI non si traducono spesso in controller simili. Ma sarebbe un’altra cosa da sperimentare. A volte c’è una vittoria, a volte non c’è.

Ho scritto un articolo su questo argomento, tra cui alcuni suggerimenti per lavorare con STI:

Ereditarietà di tabelle singole in Rails

In breve: deve esserci una chiara relazione di ereditarietà in stile OO tra gli oggetti (come affermato eloquentemente da womble), non solo alcuni dati condivisi. Se non esiste una gerarchia di classi naturale e ovvia, un progetto STI può diventare difficile da mantenere man mano che l’applicazione si evolve.

In secondo luogo, dovresti considerare se è importante avere tutti i dati in una tabella. Con le associazioni polimorfiche, le query del database diventeranno più complesse e probabilmente più lente. Se stai pianificando di elencare tutti gli oggetti sul sito (ad esempio, in una tabella), allora STI potrebbe essere la strada da percorrere.

In terzo luogo, assicurati che le tue classi figlio non abbiano troppi attributi unici. Con tutti i dati in una tabella, non vuoi molte colonne non globali. Non solo occupano spazio (non è una preoccupazione importante), ma rendono la struttura dei dati confusa. Se hai colonne “speciali” dovresti spiegarle esplicitamente nel tuo codice.

Infine, se si utilizza STI, si consiglia vivamente di utilizzare un singolo controller per tutti i modelli figlio. La funzione principale di un controller è quella di fornire accesso agli oggetti, e se gli oggetti devono essere accessibili in modi molto diversi, allora STI potrebbe non essere stata la scelta di progettazione corretta per cominciare.

Controlla il mio articolo (link sopra) per alcuni consigli più utili.

Probabilmente userei STI o nessuna funzionalità speciale. Potresti essere in grado di chiamare tutto un profilo e sapresti se era un “bot” se il suo utente era zero. È anche ansible memorizzare un campo “tipo” senza utilizzare STI.

Alcune cose potrebbero influenzare la mia decisione di usare STI:

  • Se esiste una logica specifica per i bot
  • Quanti robot ci sono contro i profili degli utenti (un piccolo numero di bot significa che STI è OK, molti robot e io li posso memorizzare altrove)

Il motivo per evitare STI a volte può essere d’intralcio. Ad esempio può essere abbastanza fastidioso cambiare un object da un tipo all’altro (un Bot in un profilo in questo caso). A volte un semplice campo di “tipo” è migliore.

Vale la pena notare che probabilmente si vorrà una class base comune se si utilizza STI. Quindi potresti volere Profile , BotProfile e UserProfile . I nomi dipendono da te. 🙂

Una traccia di Rails STI: la maggior parte dei plugin (e così via) non la supporta completamente. Ti troverai a rattoppare molti di quelli comuni.