Коллекция Ruby / Rails в коллекцию

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

Library
Book
LibraryBooks

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

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

Я подумал:

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

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

Итак, вы хотите, чтобы во всех библиотеках были книги? Приведенный выше фрагмент кода не будет возвращать ту же библиотеку, что и l. Это все равно, что спрашивать у всех ваших книг, кто их владелец. Небольшая путаница ... но ответ Джима ниже подойдет для трюка с сопоставлением.

Gishu 17.09.2008 07:55

Во всех библиотеках есть книги, которые тоже есть в этой библиотеке, да?

Jim Puls 17.09.2008 08:04

@ Джим - это именно то, что я хочу

aronchick 25.09.2008 03:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
3
5 453
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Возможно:

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

Это не совсем так, в зависимости от того, что было загружено изначально.

Jim Puls 17.09.2008 20:29

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

Ben Scofield 22.09.2008 18:23

упс ... не уверен, что это работает ... вы имели в виду LibraryBook или Library?

aronchick 25.09.2008 03:36
Ответ принят как подходящий

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

медленность Symbol # to_proc обычно перевешивается вызовами базы данных.

Jim Deville 26.09.2008 03:16

Я не понимаю, как это могло работать. Первая строка вернет массив объектов библиотеки (на самом деле прокси, но с теми же методами). В этом массиве не будет метода "книги", поэтому вторая строка не удастся, не так ли?

MiniQuark 27.11.2008 23:05

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