Pergunta

Eu tenho duas tabelas unidas a uma tabela de junção - isso é apenas pseudocódigo:

Library
Book
LibraryBooks

O que preciso fazer é se eu tiver o id de uma biblioteca, quero obter todas as bibliotecas em que estão todos os livros que esta biblioteca possui.

Então, se eu tenho a Biblioteca 1, e a Biblioteca 1 contém os livros A e B, e os livros A e B estão nas Bibliotecas 1, 2 e 3, existe uma maneira elegante (uma linha) de fazer isso no Rails?

Eu estava pensando:

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

Mas isso não parece funcionar.Sugestões?

Foi útil?

Solução

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

Observe que map(&:library_ids) é mais lento que map { |b| b.library_ids } no Ruby 1.8.6 e mais rápido no 1.9.0.

Devo também mencionar que se você usou :joins em vez de include lá, ele encontraria a biblioteca e os livros relacionados, todos na mesma consulta, acelerando o tempo do banco de dados. :joins entretanto, só funcionará se uma biblioteca tiver livros.

Outras dicas

Talvez:

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

ou

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

se você quiser tudo em uma matriz plana.

Claro, você realmente deve definir isso como um método na Biblioteca, de modo a defender a nobre causa do encapsulamento.

Se você deseja que uma matriz unidimensional de bibliotecas seja retornada, com as duplicatas removidas.

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

Um problema com

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

é que ele irá gerar uma chamada SQL para cada livro em l.Uma abordagem melhor (supondo que eu entenda seu esquema) pode ser:

LibraryBook.find(:all, :conditions => ['book_id IN (?)', l.book_ids]).map(&:library_id).uniq
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top