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?

War es hilfreich?

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top