5

Je travaille sur une très grande application Rails. Au début, nous n'utilisions pas beaucoup d'héritage, mais nous avons eu quelques expériences d'ouverture d'un consultant et nous cherchons à refactoriser certains de nos modèles.Combien de classes est trop? Rails STI

Nous avons le modèle suivant beaucoup dans notre application:

class Project < ActiveRecord::Base 
    has_many :graph_settings 
end 

class GraphType < ActiveRecord::Base 
    has_many :graph_settings 
    #graph type specific settings (units, labels, etc) stored in DB and very infrequently updated. 
end 

class GraphSetting < ActiveRecord::Base 
    belongs_to :graph_type 
    belongs_to :project 
    # Project implementation of graph type specific settings (y_min, y_max) also stored in db. 
end 

Il en résulte aussi une tonne de vues, en conditionals aides et dans le modèle GraphSetting lui-même. Rien de tout cela est bon.

Un refactoring simple où l'on se débarrasse de GraphType en faveur de l'utilisation d'une structure plus comme ceci:

class Graph < ActiveRecord::Base 
    belongs_to :project 
    # Generic methods and settings 
end 

class SpecificGraph < Graph 
    # Default methods and settings hard coded 
    # Project implementation specific details stored in db. 
end 

Maintenant, cela fait sens pour moi, facilite les tests, supprime conditionals et rend l'internationalisation plus tard plus facile. Cependant, nous n'avons que 15 à 30 graphiques. Nous avons un modèle très similaire (trop compliqué à utiliser à titre d'exemple) avec près de 100 'types' différents, et pourrait doubler cela. Ils auraient tous des relations et des méthodes qu'ils ont héritées, certains auraient besoin de remplacer d'autres méthodes que d'autres. Cela semble être l'utilisation parfaite, mais beaucoup semblent juste beaucoup.

Est-ce que 200 classes STI sont nombreuses? Y a-t-il un autre modèle que nous devrions examiner?

Merci pour toute sagesse et je répondrai à vos questions.

Répondre

4

Si les différences sont simplement dans le comportement de la classe, alors je suppose que cela ne devrait pas être un problème, et c'est un bon candidat pour STI. (Attention, je n'ai jamais essayé avec autant de sous-classes.)

Mais, si vos 200 classes STI ont chacune des attributs uniques, vous auriez besoin de beaucoup de colonnes de base de données supplémentaires dans la table principale qui seraient NULL , 99,5% du temps. Cela pourrait être très inefficace.

Pour créer quelque chose comme « l'héritage multiple de table », ce que je l'ai fait avant avec le succès était d'utiliser un peu metaprogramming d'associer d'autres tables pour les détails propres à chaque classe:

class SpecificGraph < Graph 
    include SpecificGraphDetail::MTI 
end 

class SpecificGraphDetail < ActiveRecord::Base 
    module MTI 
    def self.included(base) 
     base.class_eval do 
     has_one :specific_graph_detail, :foreign_key => 'graph_id', :dependent => :destroy 
     delegate :extra_column, :extra_column=, :to => :specific_graph_detail 
     end 
    end 
    end 
end 

Les moyens de délégation vous pouvez accéder aux champs de détail associés comme s'ils étaient directement sur le modèle au lieu de passer par l'association specific_graph_detail, et à toutes fins utiles, il semble que ce ne sont que des colonnes supplémentaires.

Vous devez remplacer les situations dans lesquelles vous devez joindre ces tables de détail supplémentaires par rapport aux colonnes supplémentaires de la table principale. Cela décidera s'il faut utiliser STI ou une solution en utilisant des tables associées, comme ma solution ci-dessus.

+0

Merci pour la réponse. À ce stade, je ne pense pas que nous aurions beaucoup (voire pas du tout) de valeurs nulles dans la base de données, comme les propriétés sont les mêmes, seulement les valeurs et les méthodes changeraient. (Par exemple, comment retourne-t-il les données pour le graphique à tracer). Si nous nous retrouvons avec des champs null (peut-être pas cette instance particulière, mais d'autres similaires), je vais certainement garder cela à l'esprit. –

+0

Il existe une autre approche similaire dans http://stackoverflow.com/questions/1634668/multiple-table-inheritance-vs-single-table-inheritance-in-ruby-on-rails/1634734#1634734 –

Questions connexes