Вопрос

У меня есть две таблицы, объединенные одной таблицей - это просто псевдокод:

Library
Book
LibraryBooks

Что мне нужно сделать, так это если у меня есть идентификатор библиотеки, я хочу получить все библиотеки, в которых есть все книги, которые есть в этой библиотеке.

Итак, если у меня есть библиотека 1, а в библиотеке 1 есть книги A и B, а книги A и B находятся в библиотеках 1, 2 и 3, есть ли элегантный (одна строка) способ сделать это в рельсах?

Я думал:

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

Но это, похоже, не работает.Предложения?

Это было полезно?

Решение

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

Обратите внимание, что map(&:library_ids) медленнее, чем map { |b| b.library_ids } в Ruby 1.8.6 и быстрее в 1.9.0.

Я также должен упомянуть, что если вы использовали :joins вместо include там он найдет библиотеку и связанные с ней книги в одном запросе, что ускорит работу базы данных. :joins Однако будет работать только в том случае, если в библиотеке есть книги.

Другие советы

Возможно:

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

или

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

если вы хотите, чтобы все это было в плоском массиве.

Конечно, вам действительно следует определить это как метод библиотеки, чтобы поддержать благородное дело инкапсуляции.

Если вы хотите вернуть одномерный массив библиотек с удаленными дубликатами.

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

Одна проблема с

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

заключается в том, что он будет генерировать один SQL-вызов для каждой книги в l.Лучшим подходом (при условии, что я понимаю вашу схему) может быть:

LibraryBook.find(:all, :conditions => ['book_id IN (?)', l.book_ids]).map(&:library_id).uniq
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top