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