ruby on rails - references - RoR: has_one "u otro"?(O, polimorfismo sin la herencia.)
rails model references (2)
Hola a todos, tengo algo de un requisito interesante para mi proyecto. Necesito una relación has_one
donde sea una clase o la otra, pero sin herencia. Podría salirme con la herencia si fuera la única forma, pero los dos registros asociados tienen datos completamente diferentes y no están relacionados en absoluto.
Lo que necesito averiguar es algo como lo siguiente.
# 1. Foo never belongs to anything.
# 2. Foo MUST have one assigned sub-record for validity.
# 3. Foo can only have either Bar or Baz assigned.
# 4. Bar and Baz have only ONE common property, and aren''t
# related in either data or implementation.
class Foo < ActiveRecord::Base
# Attributes: id, name, value
has_one :assignment, :foreign_key => ''assigned_to'', :readonly => true
# Could really use an :object_type for has_one here...
end
class Bar < ActiveRecord::Base
# Attributes: name,...
end
class Baz < ActiveRecord::Base
# Attributes: name,...
end
Donde Foo
tiene una asignación, de tipo Bar
o Baz
; solo comparten una columna común, así que quizás pueda hacer un objeto principal a partir de eso. Sin embargo, si los hago heredar de un objeto común (cuando los datos que contienen realmente son naranjas y manzanas) ¿debo hacer una tabla para el registro? ¿Puedo quizás salirse con la suya si el registro es un registro abstracto, pero los niños no?
Supongo que ahora puedes ver mi dificultad. Soy bastante nuevo en RoR pero me encanta hasta ahora. Estoy seguro de que hay una forma de evitar esto, pero seré condenado si no puedo descubrir qué es.
Está tratando de modelar algo que no se ajusta al paradigma de la base de datos relacional. Todas las referencias en SQL tienen un origen y un objetivo.
FWIW, Polymorphic Associations es también un antipatrón porque rompe esta regla. Debería ser una pista de que se trata de un diseño roto cuando la documentación dice que debe renunciar a una restricción de integridad referencial para que funcione.
Necesitas que Foo tenga dos relaciones has_one
: una para Bar y otra para Baz. Luego, implemente una lógica de clase para intentar asegurar que solo se rellene una referencia en cualquier instancia de Foo. Es decir, de las referencias a Bar y Baz, uno debe tener un valor y el otro debe ser nulo, pero esto es algo que su código debe verificar y aplicar.
Quizás una forma de hacer esto sea crear asociaciones de uno para Foo, para Bar y Baz. Luego crea un método llamado asignación y asignación = que puede ser la única forma de acceder a Bar y Baz. Puede verificar cuál de los dos has_ones no es nulo en el método get y devolver ese. En el método de asignación, puede -verificar cuál es el tipo de variable pasada y establecer la relación correcta de tener-uno con ese objeto y establecer el otro en cero. Eso debería cubrir todas tus bases sin ser demasiado complicado.