Question

J'ai deux tables jointes à une table de jointure - il ne s'agit que de pseudo-code:

Library
Book
LibraryBooks

Ce que je dois faire, c'est que si j'ai l'identifiant d'une bibliothèque, je veux obtenir toutes les bibliothèques contenant tous les livres de cette bibliothèque.

Donc, si j'ai la bibliothèque 1 et que la bibliothèque 1 contient les livres A et B, et que les livres A et B se trouvent dans les bibliothèques 1, 2 et 3, existe-t-il un moyen élégant (une ligne) de le faire dans les rails?

Je pensais:

l = Library.find(1)
allLibraries = l.books.libraries

Mais cela ne semble pas fonctionner. Suggestions?

Était-ce utile?

La solution

l = Library.find(:all, :include => :books)
l.books.map { |b| b.library_ids }.flatten.uniq

Notez que map (& amp;: library_ids) est plus lent que map {| b | b.library_ids} dans Ruby 1.8.6, et plus rapide dans 1.9.0.

Je devrais également mentionner que si vous utilisiez : joint au lieu de include , la bibliothèque et les livres associés seraient tous trouvés dans la même requête, ce qui accélèrerait le temps de la base de données. . : join ne fonctionnera que si une bibliothèque a des livres.

Autres conseils

Peut-être:

l.books.map {|b| b.libraries}

ou

l.books.map {|b| b.libraries}.flatten.uniq

si vous voulez tout cela dans un tableau plat.

Bien sûr, vous devriez définir cela comme une méthode sur Library, afin de défendre la noble cause de l'encapsulation.

Si vous souhaitez obtenir un tableau unidimensionnel de bibliothèques, en supprimant les doublons.

l.books.map{|b| b.libraries}.flatten.uniq

Un problème avec

l.books.map{|b| b.libraries}.flatten.uniq

est que cela va générer un appel SQL pour chaque livre dans l. Une meilleure approche (si je comprends votre schéma) pourrait être:

LibraryBook.find(:all, :conditions => ['book_id IN (?)', l.book_ids]).map(&:library_id).uniq
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top