Rieles: ¿usar columna de tipo sin STI?

81

Quiero usar una columna llamada typesin invocar la herencia de tabla única (STI); solo quiero typeser una columna normal que contenga una extensión String.

¿Cómo puedo hacer esto sin que Rails espere que tenga una herencia de tabla única y arroje una excepción de The single-table inheritance mechanism failed to locate the subclass...This error is raised because the column 'type' is reserved for storing the class in case of inheritance.?

¿Alguna idea sobre cómo hacer esto?

Kvass
fuente

Respuestas:

134

En Rails 3.1 set_inheritance_columnestá en desuso, también puede usarlo nilcomo un nombre, así:

class Pancakes < ActiveRecord::Base
    self.inheritance_column = nil
    #...
end
Valentin Nemcev
fuente
En realidad, parece que eso cambió rails 3.2. Según apidock : 'Este método está obsoleto o se ha trasladado a la última versión estable. Aquí se muestra la última versión existente (v3.1.0). ' ¡Gracias por el consejo!
Batkins
Fue obsoleto en 3.1 y eliminado en 3.2, creo
Valentin Nemcev
2
@Batkins El inheritance_columnlector se mueve (de ahí el aviso "en desuso o movido"). El uso de establecer la inheritance_columnvariable de instancia directamente está previsto y no está en desuso.
lulalala
Trabajado en rieles 5.1
John Bachir
21

Puede anular el nombre de la columna STI usando set_inheritance_column:

class Pancakes < ActiveRecord::Base
    set_inheritance_column 'something_you_will_not_use'
    #...
end

Así que elija un nombre de columna que no use para nada y alimente eso set_inheritance_column.

mu es demasiado corto
fuente
2
¿Necesito crear realmente dicha columna en mi base de datos?
Kvass
Gracias, esto funcionó. ¡Un marco NUNCA debería! ¡¡¡¡SIEMPRE!!!! dictar el nombre de un campo de tabla. Eso es muy malo para los conjuntos de datos heredados.
Jon
5
@Jon: Rails realmente no se preocupa por los datos heredados o por jugar bien con los demás, Rails tiene demasiada actitud para eso. Puedes hacer que se comporte con algo de esfuerzo, pero siempre terminas peleando un poco si necesitas hacer algo que Rails no ha planeado (que desafortunadamente incluye muchos conceptos básicos de bases de datos). OTOH, soy un hereje profesional, por lo que otras personas de Rails ciertamente estarán molestas conmigo por señalar los problemas ideológicos :)
mu es demasiado corto
10
Creo que la idea es que Rails / Ruby prefieren la convención a la configuración, por lo que intentan optimizarla para los casos de uso que consideran correctos.
Ibrahim
21

Sé que esta pregunta es bastante antigua y se desvía un poco de la pregunta que está haciendo, pero lo que siempre hago cuando siento la necesidad de nombrar un tipo de columna o algo_tipo es buscar un sinónimo de tipo y usarlo en su lugar:

Aquí hay un par de alternativas: tipo, clasificación, variedad, categoría, conjunto, género, especie, orden, etc.

rii
fuente
10

Rieles 4.x

Encontré el problema en una Rails 4aplicación, pero en Rails 4 el set_inheritance_columnmétodo no existe en absoluto, por lo que no puede usarlo.

La solución que funcionó para mí fue deshabilitar la herencia de tabla única anulando ActiveRecordel inheritance_columnmétodo, como este:

class MyModel < ActiveRecord::Base

  private

  def self.inheritance_column
    nil
  end

end

¡Espero eso ayude!

Itay Grudev
fuente
8
Versión más simple: class MyModel < ActiveRecord::Base self.inheritance_column = nil end. Referencia: apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/…
Benj
1
Me funciona en rieles 4.2.2. ¿Quizás no reinició el servidor o el resorte después de hacer el cambio?
Benj
1
Y otros usuarios pueden encontrar útil la versión más simple que comenté. En cuanto al problema de la recarga, no soy un experto, pero para mí tendría sentido que una propiedad de clase no se recargue automáticamente sin descargar y recargar la definición de clase.
Benj
2
No entiendo su reacción, solo estoy tratando de agregar una adición útil a su respuesta. ¿Por qué te sientes ofendido? Vengo en paz
Benj
2
@Benj Parece que eliminaron los comentarios a los que te refieres, así que ahora parece que estás discutiendo contigo mismo. ;)
Joshua Pinter
0

Si desea hacer esto para todos los modelos, puede pegarlo en un inicializador.

ActiveSupport.on_load(:active_record) do
  class ::ActiveRecord::Base
    # disable STI to allow columns named "type"
    self.inheritance_column = :_type_disabled
  end
end
Bill Lipa
fuente
O mejor aún, en ApplicationRecord .
Alexander