Relazioni polimorfiche many to many

Ciao a tutti,

mi sto scervellando su un problema non banale.

Ho la necessità di dover collegare ‘n’ modelli tra di loro, es.:

Zone
Prodotti
Fornitori
Categorie
Alberghi
Strutture
ecc.

Il problema è che dovrei fare in modo che ad esempio data una zona possa
“abbinare” n prodotti, n fornitori, n categorie, n zone (self
reference), stessa cosa però vale per tutti gli altri modelli, avrei
anche necessità di recuperare la relazione dall’altro lato (double-side
relation) es.

se abbino n prodotti ad una zona, a partire dal prodotto voglio vedere
tutte le zone collegate ecc.

Ora, sono partito pensando ad una tabella di join (habtm) per ogni
collegamento ma arrivo ad avere un numero di tabelle di join enorme
anche solo con 7/8 tabelle => (n^2+n)/2

Sono quindi passato a provare has_many_polymorphs ma non riesco a capire
come gestire la relazione molti a molti tra tabelle diverse…

Mi spiego meglio, se gestisco un’unica tabella di join polimorfico tra
padre e figlio generico, se dal padre voglio ottenere i figli tutto bene
ma come faccio dai figli recuperare i padri non sapendo a priori se
questi sono stati inseriti come padri o come figli ?

Qualcuno si è già cimentato sulla risoluzione di un problema simile ?
(mi basterebbe avere una dritta su quale è la tecnica migliore per la
risoluzione del problema…)

Grazie 1000 !

Ti aiuterei volentieri ma sono fermo ancora alla lettura del primo
capitolo di Ruby :slight_smile:

Ciao, per darti una dritta, potresti avere un ipotetica tabella items
(nome
fittizzio) in cui avresti una colonna item_type e item_id. Questa
tabella è
polimorfica, nel senso che zone avrà molti prodotti e per trovarli andrà a
vedere i record della tabella che su item_type hanno ‘prodotto’.
Dopodichè
pescherà il record dalla tabella prodotti tramite in base al campo type_id
corrispondente

Già così è molto controverso, fare la stessa cosa per tutte le altre tabelle
(un fornitore può avere diversi prodotti) diventa un impresa quasi
impossibile con questo design. In rails 2.1 mi sembra sia possibile
accedere
alla relazione polimorfica in entrambi i sensi. Il mio consiglio è però
quello di ripensare alla struttura per renderla più semplice. Altrimenti
sarebbe solo il primo di una serie di problemi (prova a pensare alla
performance e
mantenibilità)
2008/6/16, Gianluca T. [email protected]:

Il giorno 16/giu/08, alle ore 18:45, Gianluca T. ha scritto:

Zone
Prodotti
Fornitori
Categorie
Alberghi
Strutture
[…]

Ad occhio potresti usare un has_many_through e rendere polimorfica la
relazione su Zone. Se ho più tempo dopo provo a scrivere un esempio :slight_smile:

Grazie a tutti quelli che mi hanno risposto.

Alla fine ci sono riuscito !!!

Utilizzando has_many_polymorphs è quindi possibile mettere in relazione
n tabelle con n tabelle in modalità self-referential e double-side
relationship.

Per fare questo ho installato il plugin e poi semplicemente mi sono
creato un model di collegamento many to many polimorfico:

class Link < ActiveRecord::Base
belongs_to :linker, :polymorphic => true
belongs_to :linkable, :polymorphic => true

acts_as_double_polymorphic_join :linkers => [:zones, :hostels,
:producers, :suppliers, :products],
:linkables => [:zones, :hostels,
:producers, :suppliers, :products]
end

Gli altri model non li ho toccati, per la migration ho fatto
così:
class CreateLinks < ActiveRecord::Migration
def self.up
create_table :links do |t|
t.references :linker, :polymorphic => true
t.references :linkable, :polymorphic => true

  t.timestamps
end

end

def self.down
drop_table :links
end
end

E poi l’esempio di funzionamento è questo:

Product.create(:name => “P1”)
=> #<Product id: 1, name: “P1”, created_at: “2008-06-17 13:36:31”,
updated_at: “2008-06-17 13:36:31”>

Supplier.create(:name => “S1”)
=> #<Supplier id: 1, name: “S1”, created_at: “2008-06-17 13:36:47”,
updated_at: “2008-06-17 13:36:47”>

Product.first.linkables << Supplier.first
=> [#<Supplier id: 1, name: “S1”, created_at: “2008-06-17 13:36:47”,
updated_at: “2008-06-17 13:36:47”>]

Product.first.suppliers
=> [#<Supplier id: 1, name: “S1”, created_at: “2008-06-17 13:36:47”,
updated_at: “2008-06-17 13:36:47”>]

Supplier.first.products
=> [#<Product id: 1, name: “P1”, created_at: “2008-06-17 13:36:31”,
updated_at: “2008-06-17 13:36:31”>]

Product.first.linkables
=> [#<Supplier id: 1, name: “S1”, created_at: “2008-06-17 13:36:47”,
updated_at: “2008-06-17 13:36:47”>]

Product.first.linkables << Product.find(2)
=> [#<Supplier id: 1, name: “S1”, created_at: “2008-06-17 13:36:47”,
updated_at: “2008-06-17 13:36:47”>, #<Product id: 2, name: “P2”,
created_at: “2008-06-17 13:36:33”, updated_at: “2008-06-17 13:36:33”>]

Product.first.products
=> [#<Product id: 2, name: “P2”, created_at: “2008-06-17 13:36:33”,
updated_at: “2008-06-17 13:36:33”>]

Direi FANTASTICO !!!

POSSO QUINDI ASSOCIARE QUALUNQUE COSA IO VOGLIA MEDIANTE UN’UNICA
TABELLA !!!

L’unico dubbio che mi rimane è che devo per forza associare tramite
.linkables al posto di utilizzare ad esempio .products perchè le
collezioni sono sempre frozen ma credo che questo sia “by design…”.