Ruby / Rails Коллекция в коллекцию - PullRequest
6 голосов
/ 17 сентября 2008

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

Library
Book
LibraryBooks

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

Итак, если у меня есть Библиотека 1, а в Библиотеке 1 есть книги А и В, а книги А и В - в библиотеках 1, 2 и 3, есть ли изящный (в одну строку) способ сделать это в рельсах?

Я думал:

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

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

Ответы [ 4 ]

7 голосов
/ 17 сентября 2008
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 будет работать, только если в библиотеке есть книги.

3 голосов
/ 17 сентября 2008

Возможно:

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

или

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

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

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

2 голосов
/ 17 сентября 2008

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

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

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

LibraryBook.find(:all, :conditions => ['book_id IN (?)', l.book_ids]).map(&:library_id).uniq
2 голосов
/ 17 сентября 2008

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

l.books.map{|b| b.libraries}.flatten.uniq
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...