Colección Ruby/Rails a Colección
-
09-06-2019 - |
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?
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