web-dev-qa-db-fra.com

Héritage d'une table unique et où l'utiliser dans Rails

Je suis coincé dans un problème de conception étrange,

Je travaille sur deux types de profils Modèles,

  • Profil utilisateur (appartient à l'utilisateur)
  • d'autres qui sont maintenus sur place en tant que "bots" (n'appartiennent à personne)

Le comportement typique de OO de ces deux types de profils est le même, mais seuls les attributs/propriétés importants sont communs (les très importants au nombre de 5-6), d'autres propriétés comme "intérêts, etc." ( près de 10 à 15 propriétés) ne sont pas là pour les profils de robots

Le codeur qui a travaillé sur ce précédent a créé des modèles/contrôleurs distincts pour les profils de robots/profils d'utilisateurs, ce qui crée beaucoup de redondance partout et aussi comme prévu difficile à maintenir, à écrire des tests, etc. Je voulais DRY ceci, au moins pour résoudre certains/tous ces problèmes de redondance.

Quelqu'un a suggéré l'héritage de table unique comme solution

Quelqu'un a suggéré d'utiliser des associations polymorphes à la place.

quelle est la meilleure approche. Quand utilisons-nous réellement les IST?

Ma propre pensée était que STI est mieux utilisé lorsque les attributs sont les mêmes pour les modèles et qu'ils diffèrent dans leur comportement.

Réflexions sur ce que je peux faire?

53
Rishav Rastogi

La caractérisation de STI comme étant surtout utile lorsque les attributs sont les mêmes mais que le comportement diffère est "à peu près juste", mais peut-être un peu limitative. J'aime utiliser STI quand il y a, comme son nom l'indique, une relation d'héritage de style OO claire, plutôt que la relation de style base de données entre des objets de différents types.

S'il existe un code commun entre les bots et les utilisateurs, je dirais que STI sonne comme un gagnant. S'il n'y a que quelques attributs communs, c'est probablement moins applicable mais ça vaut quand même le coup.

Je suis une personne assez expérimentale, donc ma recommandation est d'essayer. Branchez votre code et refactorisez les modèles dans une relation STI. Voyez si cela fait vraiment sécher les choses, ou échange simplement un ensemble de maux de tête contre un autre problème.

Une chose que je pense que vous ne verrez pas beaucoup d'avantages est de sécher vos contrôleurs. D'après mon expérience, les modèles STI ne se traduisent pas souvent en contrôleurs similaires. Mais ce serait autre chose à expérimenter. Parfois, il y a une victoire, parfois non.

35
womble

J'ai écrit un article sur ce sujet, y compris quelques conseils pour travailler avec STI:

Héritage de table unique dans les rails

En bref: il doit y avoir une relation d'héritage de style OO claire entre les objets (comme le dit avec éloquence womble), pas seulement quelques données partagées. S'il n'y a pas de hiérarchie de classe naturelle et évidente, une conception STI peut devenir difficile à maintenir à mesure que votre application évolue.

Deuxièmement, vous devez déterminer s'il est important d'avoir toutes les données dans un seul tableau. Avec les associations polymorphes, vos requêtes de base de données deviendront plus complexes et probablement plus lentes. Si vous envisagez de répertorier tous les objets sur le site (par exemple, dans un tableau), STI peut être le chemin à parcourir.

Troisièmement, assurez-vous que vos classes enfants n'ont pas trop d'attributs uniques. Avec toutes les données dans une table, vous ne voulez pas beaucoup de colonnes non globales. Non seulement ces derniers occupent de l'espace (ce qui n'est pas une préoccupation majeure), mais ils rendent la structure des données déroutante. Si vous avez des colonnes "spéciales", vous devez les expliquer explicitement dans votre code.

Enfin, si vous utilisez STI, je vous recommande fortement d'utiliser un seul contrôleur pour tous vos modèles enfants. La fonction principale d'un contrôleur est de fournir un accès aux objets, et si les objets doivent être accédés de manières très différentes, STI n'a peut-être pas été le bon choix de conception pour commencer.

Consultez mon article (lien ci-dessus) pour quelques conseils plus utiles.

29
Alex Reisner

J'utiliserais probablement STI ou aucune fonctionnalité spéciale. Vous pourriez être en mesure d'appeler tout un profil et vous sauriez s'il s'agissait d'un "bot" si son utilisateur était nul. Vous pouvez également stocker un champ "type" sans utiliser STI.

Certaines choses pourraient affecter ma décision d'utiliser les IST:

  • S'il existe une logique spécifique au bot
  • Combien de robots il y a par rapport aux profils d'utilisateurs (un petit nombre de robots signifie que STI est OK - beaucoup de robots et je pourrais les stocker ailleurs)

La raison pour éviter les IST est parfois qu'elles peuvent vous gêner. Par exemple, il peut être assez ennuyeux de changer un objet d'un type à un autre (un Bot à un Profil dans ce cas). Parfois, un simple champ "type" est préférable.

Il vaut la peine de noter que vous voudrez probablement une classe de base commune si vous utilisez STI. Vous pouvez donc vouloir Profile, BotProfile et UserProfile. Les noms vous appartiennent. :)

5
wuputah

Un piège de Rails STI - la plupart des plugins (et ainsi de suite) ne le supportent pas complètement. Vous vous retrouverez à patcher bon nombre des plus courants.

4
Sarah Mei