12

un poco de ayuda si se quiere.asociaciones de escritura para una relación recursiva

Me gustaría crear una relación recíproca con mi clase 'producto'. Donde puedo tener un producto sea el producto principal para otros productos. Mi pregunta es ¿cómo creo esta relación dentro de mi modelo?

¿Esto sería apropiado?

has_many :products 
belongs_to :product 

Respuesta

38

Hay lógicamente nada malo con la solución propuesta. Sin embargo, es probable que tenga que hacer algo como esto:

belongs_to :parent, class_name: "Product", foreign_key: "parent_id" 
has_many :children, class_name: "Product", foreign_key: "parent_id" 

Usted es básicamente el almacenamiento de un "árbol", con un producto en la parte superior y las ramas de productos niño debajo, potencialmente muchos niveles de profundidad.

La estrategia en su ejemplo se conoce como Adjacency List. Es fácil encontrar al padre directo y a los descendientes directos de cualquier registro dado. Sin embargo, obtener TODOS los descendientes (incluidos los descendientes de descendientes) puede ser difícil, y se vuelve más difícil cuanto más profundo es el árbol.

Una alternativa de uso frecuente es Nested Set, donde cada registro almacena información sobre el objeto a la "izquierda" y a la "derecha" del mismo. Esto le permite construir un árbol, no importa cuán grande, bastante rápido (o al menos eficientemente, en una sola consulta). Sin embargo, es más complicado e insertar un registro generalmente significa tener que recalcular y actualizar todos los registros a la derecha del registro que ha insertado.

Una tercera opción (y posiblemente una especie de término medio) es usar Path Enumeration, donde los objetos almacenan toda su ruta en el árbol. Por lo tanto, dado un árbol como este:

A 
/\ 
B C 
    | 
    D 

A tendría una ruta en blanco (sin los padres), y BC tendría el camino A, D tendría el camino A/C. La mayoría de las operaciones de inserción son relativamente económicas con esta solución, y la consulta es bastante fácil. Sin embargo, sus objetos bastante complejos y en movimiento en el árbol pueden ser costosos. También hay otras opciones, como Closure Tables.

Si una lista de adyacencia simple funciona para sus necesidades, entonces vaya con eso. Definitivamente es el más simple y fácil de entender. Hay gemas que implementan conjuntos anidados, y tal vez también para algunos otros patrones de árbol, por lo que no tienes que hacer todo el trabajo pesado por ti mismo si vas por esa ruta.

+0

wow! respuesta increíble, gente como tú hace que sitios como este sean geniales. ¡Gracias! –

+0

[Esta respuesta] (http://stackoverflow.com/a/11162888/638425) puede ser útil al implementar el patrón Tablas de cierre. – elhoyos

+0

¡Gran respuesta, gracias por esto! Es útil para hacer cosas como comentarios en publicaciones con un modelo. – Tomanow

Cuestiones relacionadas