2012-07-26 12 views
25

En Los Carriles 3.2.6, tengo una clase que hereda de ActiveRecord :: Base:Prevenir las ITS al heredar de un modelo ActiveRecord

class Section < ActiveRecord::Base 
    ... 
end 

Cuando heredar de esta clase, los carriles asumirá Quiero ITS:

class AnotherSection < Section 
    ..Rails assumes I have a type field, etc... 
end 

quiero ser capaz de heredar de la clase Section y el uso de la subclase como una subclase normal de Ruby, sin la magia rieles ITS.

¿Hay alguna manera de evitar las ITS cuando se subclasan desde un modelo ActiveRecord::Base?

+2

si no tiene una columna de 'tipo' que no debería molestarle ... si tiene un 'tipo', entonces puede desactivarlo haciendo lo que @Veraticus dijo ... – shuriu

+0

De hecho, usted todavía tener STI: las instancias de ambas clases se almacenarán en la misma tabla, ¿cuál es la definición de ITS (herencia de tabla única)? Simplemente no desea tener una columna discriminatoria (el "tipo"). Sin embargo, ¿cómo sabrá si cada registro de las secciones es una sección simple o una OtraSección? – atorres

Respuesta

28

Esto se puede conseguir mediante la desactivación de la inheritance_column para el modelo, así:

class AnotherSection < Section 
    # disable STI 
    self.inheritance_column = :_type_disabled 

end 
+7

Eso o cualquier columna inexistente es suficiente. – shuriu

+3

self.inheritance_column = nil funcionó para mí (pero lo probé hace mucho tiempo y fue carriles 3.2) – Alexis

+0

esto deshabilita la columna discriminador. Pero ambas clases se almacenan en la misma tabla, ¿cuál es la definición de IET (herencia de tabla única)? Acaba de eliminar la columna del discriminador, y Ruby no podrá decidir cuál es el tipo de cada registro almacenado (deberá decidir cuándo cargar) – atorres

11

La respuesta aceptada definitivamente trabajar, pero el recomendado (me atrevería a decir "adecuado" :) forma de hacerlo es establecer abstract_class :

class Section < ActiveRecord::Base 
    self.abstract_class = true 
end 
+3

Este es el enfoque correcto, y ha estado presente desde Rails 1.1. –

+0

Esto no funciona para mí. No puedo instanciar ningún objeto de esta clase de modelo ... ('NotImplementedError: MyModel es una clase abstracta y no se puede crear una instancia.). Así que por favor revise su respuesta @smathy – deepflame

+0

@deepflame no puede instanciar una clase abstracta, es abstracta. – smathy

1

La única estrategia totalmente compatible para almacenar herencia en ActiveRecord es STI. Sin embargo, puede simular una herencia concreta de tablas de clase bajo su propio riesgo. La herencia concreta de la tabla de clases con la superclase abstracta funciona bien, tal como lo señala smathy.

pero ... si lo que quiere es hacer AnotherSection simplemente una clase ordinaria (que no se conservará en la base de datos), que podría desactivar la columna discriminadora (según lo sugerido por Veraticus). Sin embargo, si guarda el AnotherSection, se mantendrá en la misma tabla que Sección, y no podrá diferenciarlos. Además, si se utiliza AnotherSection encontrar un Sección, se devolverá un AnotherSection, rompiendo la creación de instancias originales:

#create a Section and saves it 
    sect = Section.create() 
    sect.save() 
    #retrieve the Section as a AnotherSection, breaking polymorphism... 
    sect = AnotherSection.find(sect.id) 
    # another section is more than a section, it is inconsistent. 

Si AnotherSection no pretende ser persistido, el camino más seguro que para anular las operaciones de persistencia, como Save() y encontrar():

class AnotherSection < Section 
     # disable STI, as pointed by Veraticus 
     self.inheritance_column = :_type_disabled 
     # disable save and finding 
     def save(*args) 
     #exception? do nothing? 
     end 
     def find(*args) 
     #exception? do nothing? 
     end 
     def find_by(*args) 
     #exception? do nothing? 
     end 
     # this does not stops here! there is first, last, and even a forty_two finder method! not to mention associations... 
    end 

en pocas palabras, se puede hacer esto, pero No deberías. El riesgo es alto Debería considerar otra opción, como usar MIXIN en lugar de herencia.

Cuestiones relacionadas