5

Estoy trabajando en una aplicación Rails muy grande. Inicialmente no usamos mucha herencia, pero hemos tenido algunas experiencias de apertura de un consultor y estamos buscando refactorizar algunos de nuestros modelos.¿Cuántas clases son demasiadas? Rails STI

Tenemos el siguiente patrón mucho en nuestra aplicación:

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 

Esto también se traduce en una tonelada de condicionales en las vistas, ayudantes y en el propio modelo de GraphSetting. Nada de esto es bueno.

Un refactor simple donde nos deshacemos de GraphType en favor del uso de una estructura de la misma familia:

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 

Ahora bien, esto tiene mucho sentido para mí, facilita las pruebas, elimina los condicionales, y hace más adelante internacionalización más fácil. Sin embargo, solo tenemos de 15 a 30 gráficos.

Tenemos un modelo muy similar (complicado de usar como ejemplo) con cerca de probablemente 100 'tipos' diferentes, y podría duplicar eso. Todos tendrían relaciones y métodos que heredarían, algunos necesitarían anular más métodos que otros. Parece el uso perfecto, pero parece que muchos simplemente parecen muchos.

¿Hay 200 clases de STI para muchas? ¿Hay algún otro patrón que deberíamos mirar?

Gracias por su sabiduría y responderé a cualquier pregunta.

Respuesta

4

Si las diferencias son solo en el comportamiento de la clase, entonces supongo que no debería ser un problema, y ​​este es un buen candidato para STI. (Fíjate, nunca lo he intentado con tantas subclases)

Pero, si tus 200 clases de STI tienen cada una atributos únicos, necesitarías muchas columnas extra de base de datos en la tabla maestra que serían NULL , 99.5% del tiempo. Esto podría ser muy ineficiente.

crear algo así como "herencia de tablas múltiple", lo que he hecho antes con éxito fue usar un poco metaprogramming asociar otras tablas para los detalles únicos para cada clase:

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 

Los medios de delegación puede acceder a los campos de detalles asociados como si estuvieran directamente en el modelo en lugar de pasar por la asociación specific_graph_detail y, a todos los efectos, se "ve" como si fueran columnas adicionales.

Tiene que compensar las situaciones en las que necesita unir estas tablas de detalles adicionales con solo tener las columnas adicionales en la tabla maestra. Eso decidirá si se usa STI o una solución usando tablas asociadas, como mi solución anterior.

+0

Gracias por la respuesta. En este punto, no creo que tengamos muchos (si los hubiera) valores nulos en la base de datos, ya que las propiedades son las mismas, solo cambiarían los valores y métodos. (Por ejemplo, cómo devuelve los datos del gráfico para trazarlos). Si terminamos con campos nulos (tal vez no esta instancia en particular, pero otros similares) Sin duda tendré esto en cuenta. –

+0

Hay otro enfoque similar en http://stackoverflow.com/questions/1634668/multiple-table-inheritance-vs-single-table-inheritance-in-ruby-on-rails/1634734#1634734 –

Cuestiones relacionadas