8
votes

Rôles d'utilisateur multiple dans Ruby sur rails

Je construis une application de gestion des stocks avec quatre types d'utilisateurs différents: admin, employé, fabricant, transporteur. Je n'ai pas encore commencé à coder, mais c'est ce que je pense. Les fabricants et les transporteurs sont liés avec HAS_MANY: par l'intermédiaire de nombreuses à-plusieurs associations avec des produits comme suit:

class Manufacturer < ActiveRecord::Base
 has_many :products
 has_many :transporters, :through => :products
end

class Product < ActiveRecord::Base
 belongs_to :manufacturer
 belongs_to :transporter
end

class Transporter < ActiveRecord::Base
 has_many :products
 has_many :manufacturers, :through => :products
end


0 commentaires

3 Réponses :


1
votes

Je vous suggère de créer un modèle d'utilisateur, un modèle d'adresse, un modèle de contactInfo, etc. Vous ne devez pas disposer de ces types de champs dans le modèle utilisateur. Normaliser la base de données. Avoir un FK dans chacune de ces autres classes à user.id.

Si vous devez les garder séparés, alors normaliser les connexions et le rendre polymorphe à référencer son propriétaire (fabricant, employé, etc.)


7 commentaires

Weeeelll ... peut-être. Avoir une table des adresses est certainement normalisé, mais dans le monde réel, plusieurs fois, il est trop exclu et, en fait plus souvent que même les monstres de normalisation les plus acharnés, les monstres de normalisation les plus difficiles admettront que quelque chose comme une adresse - ce qui ne représente dans la plupart des cas à rien de plus qu'un champ de varchar - n'a pas besoin d'être normalisé dans sa propre table avec toutes les frais générales qui subissent. Voulez-vous vraiment que SQL Rejoignez-vous à la requête des utilisateurs jamais utilisateurs? Pas très performant pour une opération aussi simple. Tellement dépend du domaine et si les adresses sont vraiment complexes et réutilisables, etc.


@Dave Sims - Je suis complètement en désaccord avec respect. Dans le monde d'aujourd'hui, nous avons besoin autant d'informations que possible. La normalisation (en particulier avec les adresses) permet une expansion future - nous pouvons permettre à un utilisateur d'avoir plusieurs adresses (à la maison et au travail par exemple). Et, si SELECT * retourne 10 colonnes ou rejoindre les rendements 10 colonnes, cela n'a pas d'importance (comme la surcharge est littéralement insignifiante pour des jeux de données encore incroyablement volumineux). De plus, vous ne montrerez pas toujours une adresse avec un utilisateur, alors pourquoi l'auriez-vous dans la table des utilisateurs? C'est un objet séparé


@Dave sims - (exclus). Je le regarde de cette façon. J'ai un prénom, j'ai un nom de famille. J'ai aussi des adresses. Je n'ai pas d'adresse_line_1 et adresse_1line_2, zip ..., une adresse a une adresse_line_1, 2....zip, etc. Pour moi, cela fait de la place plus sens à avoir ces choses séparées. Pouvez-vous avoir un utilisateur sans adresse? Voulez-vous vraiment restreindre l'accès à votre site si quelqu'un est sans abri? Je suis sur le dessus, mais je pense que vous verrez pourquoi la normalisation est importante.


@ Seth.Vargo: C'est une bonne énoncé des avantages connus de la normalisation, mais vous devez également reconnaître que ces avantages sont à un coût pourraient ne pas avoir de sens pour chaque application. La sur-normalisation peut être un cas d'optimisation précoce. Dans le «monde d'aujourd'hui», nous avons constaté qu'avoir une FK pour chaque peu de données connexes peut être autant de responsabilité qu'un avantage. La montée des cadres tels que Mongo, et al, montrent que pour de nombreuses applications et la normalisation des domaines n'est pas la principale préoccupation, la performance est que les données peuvent être exprimées dans des structures d'arbres simples plutôt que dans des structures relationnelles complexes.


@ Seth.Vargo: En ce qui concerne votre affirmation sur la performance de Joinins - euh, avez-vous déjà eu dû optimiser une requête de production du monde réel? L'une des premières règles d'optimisation consiste à limiter le nombre de tables que vous adhérez à (dans la mesure du possible), et je vous assure que dans «le monde d'aujourd'hui», c'est loin d'une préoccupation insignifiante. Quant à votre pauvre gars sans abri - mec, je ne sais pas quelle normalisation a à voir avec ça. Vous pouvez avoir un champ requis / non requis ou un FK / PKID requis / non requis, appliqué au niveau du schéma, le niveau d'application ou les deux.


@ Seth.vargo: J'accepte donc un point, et en particulier dans le domaine indiqué de l'OP, oui, probablement nécessaire de se diviser dans une table d'adresse, car il semble que le type de domaine qui aurait des adresses complexes qui seraient réutilisées par plus d'une entité. Toutes les choses étant égales, commencent par un schéma normalisé et aplatir / se dénormaliser au besoin. Mais ce n'est pas une règle absolue. Il existe des cas concevables où la performance pourrait l'emporter sur la réutilisation des données / la résilience fournie par la normalisation.


Dans mon avis très humexe: il existe un avantage clair pour avoir une base de données normalisée impliquant un refactoring, tandis que le stockage de la valeur clé, comme MongoDB ferait, peut souvent être pris en charge avec la mise en cache (théoriquement - vous pouvez "aplatir" vos jointures dans production avec un cache). Les bases de données relationnelles ont beaucoup plus de puissance lorsqu'il est normalisé. Si vous vous souciez de votre application et de son organisation à long terme, vous ferez mieux de normaliser votre base de données. Si vous suivez des conventions avec la normalisation (et le faire toujours), il n'est pas vraiment trop optimisé trop tôt.



5
votes

Votre approche de base semble raisonnable. Je vous conseillerais de faire une classe de base d'utilisateur et d'utiliser STI pour des types d'utilisateurs spécifiques, par exemple: xxx

... etc. De cette façon, s'il y a déjà la nécessité d'agréger plusieurs types d'utilisateurs en une seule relation quel que soit le type, vous avez une table pour décrire les utilisateurs en général. C'est une approche assez courante.

Selon la quantité d'accès à différents utilisateurs auront au système, vous voudrez peut-être consulter un gemme de gestion de rôle comme Autorisation déclarative .


2 commentaires

Merci pour l'aide! Comment les tables de base de données seraient-elles configurées pour cela, avec une classe de base d'utilisateurs et de STI pour des types d'utilisateurs spécifiques? Je suis vraiment, vraiment nouveau pour les rails :)


Vous aurez seulement une table 'utilisateurs' dans la DB. L'héritage STI / table unique utilise un champ "Type" dans une table de base (dans ce cas "Utilisateurs") pour distinguer les sous-types de la classe de base. Vous devez ajouter ce champ dans une migration. Ensuite, tous les attributs de tous les sous-types de la classe de base seront conservés dans la table des utilisateurs, même si beaucoup d'entre eux ne seront pas utilisés par des instances / rangées spécifiques. Il s'agit du compromis utilisant le modèle STI - vous pouvez avoir plusieurs champs NULL pour les attributs inutilisés, en fonction du nombre d'attributs spécifiques au sous-type.



5
votes

Pour plusieurs systèmes utilisateur, les moyens généralement préférés sont - utilisation du modèle de rôle ou de l'IST. Si vos utilisateurs peuvent avoir plusieurs rôles en même temps, comme le fabricant et le transporteur unique, le système de base de rôle serait une bonne solution. Si le rôle des utilisateurs est corrigé, je pense que vous devriez aller avec STI.


0 commentaires