Ruby/Rails da collezione a collezione
-
09-06-2019 - |
Domanda
Ho due tabelle unite con una tabella di join: questo è solo pseudo codice:
Library
Book
LibraryBooks
Quello che devo fare è se ho l'ID di una biblioteca, voglio ottenere tutte le biblioteche in cui si trovano tutti i libri di questa biblioteca.
Quindi, se ho la Biblioteca 1 e la Biblioteca 1 contiene i libri A e B, e i libri A e B sono nelle Biblioteche 1, 2 e 3, esiste un modo elegante (una riga) per farlo sui binari?
Stavo pensando:
l = Library.find(1)
allLibraries = l.books.libraries
Ma questo non sembra funzionare.Suggerimenti?
Soluzione
l = Library.find(:all, :include => :books)
l.books.map { |b| b.library_ids }.flatten.uniq
Notare che map(&:library_ids)
è più lento di map { |b| b.library_ids }
in Ruby 1.8.6 e più veloce in 1.9.0.
Dovrei anche menzionarlo se lo hai usato :joins
invece di include
lì, troverebbe la biblioteca e i libri correlati tutti nella stessa query, accelerando i tempi del database. :joins
funzionerà tuttavia solo se una biblioteca ha libri.
Altri suggerimenti
Forse:
l.books.map {|b| b.libraries}
O
l.books.map {|b| b.libraries}.flatten.uniq
se vuoi tutto in un array piatto.
Naturalmente, dovresti davvero definirlo un metodo sulla Libreria, in modo da sostenere la nobile causa dell'incapsulamento.
Se si desidera restituire un array unidimensionale di librerie, con i duplicati rimossi.
l.books.map{|b| b.libraries}.flatten.uniq
Un problema con
l.books.map{|b| b.libraries}.flatten.uniq
è che genererà una chiamata SQL per ogni libro in l.Un approccio migliore (supponendo che io comprenda il tuo schema) potrebbe essere:
LibraryBook.find(:all, :conditions => ['book_id IN (?)', l.book_ids]).map(&:library_id).uniq