through references rails many has_one has_many has_and_belongs_to_many has example belongs_to belongs and ruby-on-rails

ruby-on-rails - references - rails has_one through



Rails Single Table Heredness: ¿Cuál es la mejor forma de establecer explícitamente el tipo? (7)

Estoy usando herencia de tabla única en mi aplicación de rieles, y quiero establecer explícitamente el tipo de una instancia.

Tengo lo siguiente;

class Event < ActiveRecord::Base class SpecialEvent < Event

que se implementa a través de herencia de tabla única.

SpecialEvent.new funciona como se esperaba, pero quiero poder hacer cosas como

Event.new(:type => ''SpecialEvent'')

Entonces puedo crear diferentes subtipos fácilmente en la aplicación.

Sin embargo, esto no funciona y parece establecerse :type nil , no el valor al que lo configuré; Sospecho que esto se debe a que al llamar a Event.new está sobrescribiendo el argumento :type .

¿Alguien ha tenido una buena manera de hacer esto?


No, quiero crear instancias de subtipos, donde quiero determinar mediante programación qué subtipo son: HermanD

Podrías usar un patrón de fábrica , aunque he escuchado recientemente que la gente frunce el ceño por el uso excesivo de este patrón. Básicamente, use la fábrica para crear los tipos reales que desea obtener

class EventFactory def EventFactory.create_event(event_type) event_type.constantize.new() end end


Aparentemente, Rails no le permite configurar el Tipo directamente. Esto es lo que hago ...

klass_name = ''Foo'' ... klass = Class.const_get(klass_name) klass.new # Foo.new

Creo que .constantize es un atajo del reflector Rails. const_get es un método de Ruby en clase y módulo.


Si intentas crear instancias dinámicas de un subtipo y tienes el tipo de cadena, puedes hacer esto:

''SpecialEvent''.constantize.new()


Para mí, parece que necesitarás algo de mojo en el event#create action:

type = params[:event].delete(:type) # check that it is an expected value!!! die unless [''Event'', ''SpecialEvent''].include(type) type.constantize.new(params[:event])


Desde el principio, estoy de acuerdo en que las ITS a menudo NO son la mejor forma de tratar las cosas. Polimorfismo, sí, pero a menudo es mejor usar una asociación polimórfica que STI.

Dicho esto, tenía un sistema en el que ITS era importante. Era un sistema judicial y cosas como los casos judiciales eran notablemente similares en todos sus tipos y generalmente compartían todos sus atributos esenciales. Sin embargo, un caso civil y un caso criminal difieren en los elementos que manejan. Esto sucedió en varios niveles en el sistema, así que resumí mi solución.

https://github.com/arvanasse/sti_factory

Para resumir, utiliza un método de fábrica para aprovechar el enfoque común descrito anteriormente. Como resultado, el controlador puede permanecer neutral / ignorante del tipo particular de clase de STI que está creando.


Puede usar el método Rails safe_constantize , que asegurará que el objeto / clase realmente exista.

Por ejemplo:

def typeify(string) string.classify.safe_constantize end new_special_event = typeify(''special_event'').new


de "Pragmatic - Desarrollo web ágil con raíles 3ª edición", página 380

También hay una restricción menos obvia (con STI). El tipo de atributo también es el nombre de un método incorporado de Ruby, por lo que acceder directamente a establecer o cambiar el tipo de una fila puede dar como resultado mensajes de Ruby extraños. En su lugar, acceda a él implícitamente creando objetos de la clase apropiada, o acceda a ellos a través de la interfaz de indexación del objeto modelo, usando algo como esto:

persona [: tipo] = ''Administrador''

hombre, este libro realmente mece