5

Pracuję nad bardzo dużą aplikacją Rails. Początkowo nie używaliśmy wiele dziedziczenia, ale mieliśmy pewne doświadczenia otwierające oczy od konsultanta i zamierzamy zmienić niektóre z naszych modeli.Ile jest za dużo zajęć? Railsy STI

Mamy poniższego schematu dużo w naszej aplikacji:

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 

Powoduje to również mnóstwo warunkowych w widokach, pomocników i w modelu GraphSetting samego. Nic z tego nie jest dobre.

Prosty Refactor gdzie pozbędziemy GraphType na rzecz korzystania strukturę więcej tak:

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 

Teraz to ma sens dla mnie, ułatwia testowanie, usuwa warunkowe, i sprawia, że ​​później umiędzynarodowienie łatwiejsze. Jednak mamy tylko 15 do 30 wykresów.

Mamy bardzo podobny model (do skomplikowanego użycia jako przykładu) z blisko prawdopodobnie 100 różnymi "typami" i potencjalnie może podwoić to. Wszyscy mieliby relacje i metody, które odziedziczyli, niektórzy musieliby zastąpić więcej metod niż inni. Wydaje się, że jest to idealne zastosowanie, ale wiele z nich wydaje się być bardzo dużo.

Czy 200 klas STI jest dla wielu? Czy istnieje inny wzór, na który powinniśmy zwrócić uwagę?

Dziękuję za każdą mądrość, a ja odpowiem na wszystkie pytania.

Odpowiedz

4

Jeśli różnice dotyczą zachowania klasy, zakładam, że nie powinno to stanowić problemu i jest to dobry kandydat na STI. (Pamiętaj, nigdy nie próbowałem tego z tylu podklasami).

Ale jeśli twoje klasy 200 STI mają jakieś unikalne atrybuty, potrzebowałbyś wielu dodatkowych kolumn bazy danych w tabeli głównej, które byłyby NULL , 99,5% czasu. To może być bardzo nieefektywne.

Aby utworzyć coś w rodzaju „wielokrotnego dziedziczenia stołu”, co robiłem przed sukcesem było użyć trochę metaprogramowanie skojarzyć inne stoliki do szczegółów unikalnych dla każdej klasy:

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 

środki delegacji możesz uzyskać dostęp do powiązanych pól szczegółów tak, jakby były bezpośrednio w modelu, zamiast przechodzić przez skojarzenie specific_graph_detail, a dla wszystkich celów i celów "wygląda" tak, jakby były to tylko dodatkowe kolumny.

Musisz wymieniać sytuacje, w których musisz dołączyć do tych dodatkowych tabel szczegółów, po prostu mając dodatkowe kolumny w tabeli głównej. To zdecyduje, czy użyć STI, czy rozwiązania za pomocą powiązanych tabel, takich jak moje rozwiązanie powyżej.

+0

Dzięki za odpowiedź. W tym momencie nie sądzę, abyśmy mieli wiele (jeśli w ogóle) wartości zerowych w bazie danych, ponieważ właściwości są takie same, tylko wartości i metody uległyby zmianie. (Na przykład, jak zwraca dane dla wykreślonego wykresu). Jeśli zakończymy polami zerowymi (może nie tą konkretną instancją, ale podobnymi), na pewno będę o tym pamiętać. –

+0

Istnieje inne podobne podejście w http://stackoverflow.com/questions/1634668/multiple-table-inheritance-vs-single-table-inititance-in-ruby-on-on-1616434 # 1634734 –