12

un piccolo aiuto se vuoi.associazioni di scrittura per una relazione ricorsiva

Vorrei creare un rapporto passivo con la mia classe "prodotto". Dove posso avere un prodotto essere il prodotto principale per altri prodotti. Le mie domande sono: come posso creare questa relazione all'interno del mio modello?

sarebbe corretto?

has_many :products 
belongs_to :product 

risposta

38

C'è logicamente niente di sbagliato con la soluzione proposta. Tuttavia, probabilmente bisogno di fare qualcosa di simile:

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

Tu sei fondamentalmente memorizzando un "albero", con un solo prodotto in alto e rami di prodotti per bambini al di sotto, potenzialmente molti livelli di profondità.

La strategia nel tuo esempio è conosciuto come un Adjacency List. È facile trovare il genitore diretto e i discendenti diretti di ogni dato record. Tuttavia, ottenere TUTTI i discendenti (compresi i discendenti dei discendenti) può essere difficile, e diventa più difficile quanto più profondo è l'albero.

Un'alternativa spesso utilizzata è una Nested Set, in cui ogni record memorizza le informazioni sull'oggetto a "sinistra" e "a destra" di esso. Questo ti permette di costruire un albero, non importa quanto grande, abbastanza rapidamente (o almeno in modo efficiente, in una singola query). Tuttavia, è più complicato e inserire un record di solito significa dover ricalcolare e aggiornare tutti i record alla destra del record inserito.

Una terza opzione (e probabilmente una sorta di middle-ground) utilizza Path Enumeration, dove gli oggetti memorizzano l'intero percorso nell'albero. Quindi, dato un albero come questo:

A 
/\ 
B C 
    | 
    D 

A avrebbe un percorso vuoto (nessun genitore), B e C avrebbe il percorso A, D avrebbe il percorso A/C. La maggior parte delle operazioni di inserimento sono relativamente economiche con questa soluzione e l'interrogazione è piuttosto semplice. Tuttavia, i suoi oggetti ancora piuttosto complessi e in movimento intorno all'albero possono diventare costosi.

ci sono altre opzioni, anche, come Closure Tables.

Se una semplice lista di adiacenze funziona per le vostre esigenze, passateci. È sicuramente il più semplice e facile da capire. Ci sono gemme che implementano insiemi annidati, e forse anche per alcuni altri tipi di albero, quindi non devi fare tutto il lavoro pesante se passi questa strada.

+0

Eeeek !!! risposta fantastica, le persone come te fanno siti come questo fantastico. Grazie! –

+0

[Questa risposta] (http://stackoverflow.com/a/11162888/638425) può essere utile quando si implementa il modello Tabelle di chiusura. – elhoyos

+0

Ottima risposta, grazie per questo! È utile per fare cose come i commenti sui post con un modello. – Tomanow