Progettazione di database per un sistema di accesso basato sui ruoli?

2

Sto prendendo in considerazione diversi progetti per una gemma generica per la biblioteca di ruolo.

Il primo è basato sulla Rolify gem ma con una relazione has_many through: invece di HABTM. Le tabelle HABTM sono "senza testa" in ActiveRecord e non possono essere interrogate direttamente, il che è un enorme problema.

class User < ApplicationRecord
  has_many :user_roles
  has_many :roles, through: :user_roles
end 

class UserRole < ApplicationRecord
  belongs_to :user
  belongs_to :role
end 

class Role < ApplicationRecord
  has_many :user_roles
  has_many :users, through: :user_roles
  belongs_to :resource, polymorphic: true
end 

Guardandoaquesto,nonriescoavederealcunvantaggioperavereunatabellaseparatarispettoauniredirettamentegliutentiairuoli.

classUser<ApplicationRecordhas_many:rolesendclassRole<ApplicationRecordbelongs_to:userend

Avereunatabellaruoliseparataticonsenteforsedicreareruoli"globali" e quindi associare gli utenti al ruolo.

Ma vale davvero la pena della performance e ha aggiunto la complicazione, lasciando che i ruoli siano unici per utente?

    
posta papirtiger 28.09.2016 - 13:49
fonte

3 risposte

3

Having a separate Role table lets you perhaps create "global" roles and then attach users to the role.

But is it really worth the performance hit and added complication vs letting the roles be unique per user?

Assolutamente. Il vantaggio di avere ruoli preimpostati / salvati che sono disponibili per essere assegnati a diversi utenti è:

  1. È possibile testare ogni ruolo, quindi è possibile affidarlo a un utente.
  2. I dati duplicati sono più difficili da modificare.
  3. Più facile per l'amministratore assegnare il ruolo se è già stato creato. Il record viene anche aggiunto senza la necessità di duplicare i dettagli del ruolo.
  4. È importante strutturare i dati per le prestazioni, ma unire le 3 tabelle non dovrebbe essere un problema da risolvere.

Se vuoi costruire una libreria di ruoli generica, probabilmente hai bisogno della flessibilità di gestione dei dati fornita da un RDBMS. La relazione molti-a-molti che stai creando è abbastanza comune e non dovrebbe essere così difficile da lavorare.

    
risposta data 28.09.2016 - 19:15
fonte
1

Hmm ... non c'è quasi nessun riscontro in termini di prestazioni per avere la tabella di giunzione (ad es. la tabella user_roles). Meno di millisecondi: finora, nel rumore, non avresti nemmeno intravisto alcuna differenza.

Questa tabella di giunzione è un progetto di normalizzazione standard ed è piuttosto raccomandata. Se hai un ruolo di amministratore, nel tuo secondo metodo suggerito non hai modo di "controllare" che in realtà ... potresti inserire accidentalmente "Admine" invece di "Admin", quindi ti sono delle interruzioni di applicazione (o anche peggio, alcuni errori permettono alla persona sbagliata di accedere a qualcosa).

L'unico modo per garantire che il ruolo di "admin" sia corretto è quello di avere un elenco principale di ruoli unici. Il tuo secondo suggerimento non ha questo.

Ci sono davvero molti motivi per farlo in modo "corretto", con una tabella di giunzione, ma approfondire tutti vorrebbe dare lezioni sulla normalizzazione del database, che è un argomento di notevole ampiezza, profondità e molto dei fondamenti.

    
risposta data 28.09.2016 - 14:41
fonte
1

Generalmente quando si valuta la fattibilità delle prestazioni di un progetto di database non è sufficiente considerare il numero di tabelle che vengono unite per una query tipica. Si deve anche valutare la quantità di dati contenuti nelle tabelle. Se ci fossero decine di milioni di record utente, potresti avere un caso per iniziare a preoccuparti delle prestazioni, tuttavia la maggior parte dei sistemi non deve preoccuparsi di questo numero di utenti, almeno inizialmente.

Secondo me, il tuo secondo modello è difettoso. Si crea una relazione uno a uno tra ruolo e utente. Ciò significa che se hai un ruolo chiamato amministratore, allora può esserci un solo record utente che può avere quel ruolo.

Hai due opzioni. Uno è usando la tabella di mappatura / giunzione che hai definito nel tuo primo diagramma. In genere utilizziamo queste tabelle di giunzione per creare una relazione molti-a-molti tra due tabelle.

  1. Un utente può avere più di un ruolo? (True | false)
  2. Un ruolo può avere più di un utente assegnato? (True | false)

Se rispondi True a entrambe queste domande, è necessaria una tabella di giunzione.

Se hai risposto False alla domanda 1, allora forse più appropriato è un vincolo di chiave esterna definito per la colonna ID ruolo nella tabella Utente. Questo ti offre una relazione One-to-One con la tabella dei ruoli da utente e una relazione uno a uno dai ruoli agli utenti.

    
risposta data 28.09.2016 - 14:56
fonte