Ruby / Rails-Sammlung Sammlung
-
09-06-2019 - |
Frage
Ich habe eine zwei Tabellen mit einer Join-Tabelle verbunden - das ist nur Pseudo-Code:
Library
Book
LibraryBooks
Was ich tun müssen, ist, wenn ich die id einer Bibliothek haben, möchte ich die Bibliotheken alle erhalten, die alle Bücher, die diese Bibliothek in hat sind.
Also, wenn i-Bibliothek haben 1 und Bibliothek 1 hat Bücher A und B in ihnen, und Bücher A und B sind in Bibliotheken 1, 2 und 3, ist es eine elegante (eine Zeile) Art und Weise todo diese in Schienen?
Ich dachte:
l = Library.find(1)
allLibraries = l.books.libraries
Aber das scheint nicht zu funktionieren. Vorschläge?
Lösung
l = Library.find(:all, :include => :books)
l.books.map { |b| b.library_ids }.flatten.uniq
Beachten Sie, dass map(&:library_ids)
langsamer als map { |b| b.library_ids }
in Ruby 1.8.6 und schneller in 1.9.0.
Ich sollte auch erwähnen, dass, wenn Sie :joins
statt include
dort verwendet, wäre es, die Bibliothek und die damit verbundenen Bücher alle in derselben Abfrage finden Sie die Datenbank Zeit zu beschleunigen. :joins
wird jedoch nur funktionieren, wenn eine Bibliothek Bücher hat.
Andere Tipps
Vielleicht:
l.books.map {|b| b.libraries}
oder
l.books.map {|b| b.libraries}.flatten.uniq
Wenn Sie wollen alles in einem flachen Array.
Natürlich sollten Sie wirklich definieren diese als Methode auf Bibliothek, um so die edle Sache der Verkapselung aufrecht zu erhalten.
Wenn Sie eine eindimensionale Anordnung von Bibliotheken zurückgegeben, mit Duplikaten entfernt.
l.books.map{|b| b.libraries}.flatten.uniq
Ein Problem mit
l.books.map{|b| b.libraries}.flatten.uniq
ist, dass es einen SQL-Aufruf für jedes Buch in l generieren. Ein besserer Ansatz (vorausgesetzt, ich Ihr Schema verstehen) könnte sein:
LibraryBook.find(:all, :conditions => ['book_id IN (?)', l.book_ids]).map(&:library_id).uniq