Коллекция Ruby/Rails в коллекцию
-
09-06-2019 - |
Вопрос
У меня есть две таблицы, объединенные одной таблицей - это просто псевдокод:
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