Pregunta

Tengo dos tablas unidas con una tabla de unión; esto es solo un pseudocódigo:

Library
Book
LibraryBooks

Lo que debo hacer es si tengo la identificación de una biblioteca, quiero obtener todas las bibliotecas en las que se encuentran todos los libros que tiene esta biblioteca.

Entonces, si tengo la Biblioteca 1, y la Biblioteca 1 tiene los libros A y B, y los libros A y B están en las Bibliotecas 1, 2 y 3, ¿hay una forma elegante (de una línea) de hacer esto en rieles?

Yo estaba pensando:

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

Pero eso no parece funcionar.¿Sugerencias?

¿Fue útil?

Solución

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

Tenga en cuenta que map(&:library_ids) es más lento que map { |b| b.library_ids } en Ruby 1.8.6 y más rápido en 1.9.0.

También debo mencionar que si usaste :joins en lugar de include allí, encontraría la biblioteca y los libros relacionados, todos en la misma consulta, acelerando el tiempo de la base de datos. :joins Sin embargo, solo funcionará si una biblioteca tiene libros.

Otros consejos

Tal vez:

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

o

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

si lo quieres todo en una matriz plana.

Por supuesto, realmente deberías definir esto como un método en la Biblioteca, para defender la noble causa de la encapsulación.

Si desea que se devuelva una matriz unidimensional de bibliotecas, sin duplicados.

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

Un problema con

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

es que generará una llamada SQL para cada libro en l.Un mejor enfoque (suponiendo que comprenda su esquema) podría ser:

LibraryBook.find(:all, :conditions => ['book_id IN (?)', l.book_ids]).map(&:library_id).uniq
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top