Doppio join con habtm in ActiveRecord
-
05-07-2019 - |
Domanda
Ho una strana situazione che implica la necessità di un doppio join interno. Ho provato la query di cui ho bisogno, ma non so come farcela su rotaie.
I dati
- Account (has_many: siti)
- Sito (habtm: users, appartiene_to: account)
- Utente (habtm: siti)
Ignora che sono habtm o qualsiasi altra cosa, posso renderli habtm o has_many: through.
Voglio poterlo fare
@user.accounts
o
@account.users
Quindi ovviamente dovrei essere in grado di farlo
@user.accounts < @some_other_account
E quindi avere @ user.sites include tutti i siti da @some_other_account.
Ho armeggiato con habtm e has_many: through ma non riesco a farlo per quello che voglio.
Fondamentalmente devo finire con una query come questa (copiata da phpmyadmin. Testata e funzionante):
SELECT accounts.*
FROM accounts
INNER JOIN sites ON sites.account_id = accounts.id
INNER JOIN user_sites ON sites.id = user_sites.site_id
WHERE user_sites.user_id = 2
Posso farlo? È anche una buona idea avere questo doppio join? Suppongo che funzionerebbe meglio se gli utenti avessero inizialmente l'associazione con gli account e quindi si preoccupassero invece di ottenere @ user.sites, ma funziona meglio per molte altre cose se viene mantenuto così com'è (utenti < - > siti).
Soluzione
Penso che sia meglio creare metodi personalizzati per questo, piuttosto che cercare di farlo diventare un'associazione. Ad esempio.
# in user.rb
def accounts
Account.all(:include => {:sites => :users}, :conditions => ["users.id=?", self])
end
def add_account(other_account)
other_account.sites.each do |site|
self.sites << site
end
end
# in account.rb
def users
User.all(:include => {:sites => :account}, :conditions => ["accounts.id=?", self])
end
Non testato, ma dovrebbe funzionare per un'associazione HABTM o has_many :through
. Ci sono alcune ottimizzazioni che puoi effettuare con la query in base all'approccio con cui segui.
Un giorno potremmo ottenere supporto per nidificati in profondità <=> che gestiranno parte di questo.
Altri suggerimenti
Questo potrebbe esserti utile (Rails 2.x)