Как получить связанные предметы через средний класс в Rails ActiveRecord - PullRequest
0 голосов
/ 29 марта 2011

Я думаю, что это может быть довольно простой проблемой ActiveRecord, но если у меня есть запрос вроде:

@store = Store.find params[:id]
@categories = @store.categories.all

, где, скажем, @categories = @store.categories.all возвращает как 3 объекта.Затем я хочу сделать запрос, в котором я получаю все ассоциированные items, которые имеют тот же category_id, я попытался:

@categories.items

Но это не сработало, идеи?

Ответы [ 4 ]

4 голосов
/ 29 марта 2011

Я думаю, что вы ищете, скажем, если у нас есть категория 1, категория 2 и категория 3, вы хотите, чтобы все элементы принадлежали к любой из этих категорий. Это верно?

Это может быть решено с помощью итераций или ручных условий для одного запроса, но звучит как работа для has_many :through.

class Store < ActiveRecord::Base
  has_many :items, :through => :categories
end

После этого @store.items должен вернуть все предметы, принадлежащие к любой из категорий магазина. У магазина есть связь с определенными предметами через объект категории.

Если вы опасаетесь создавать такие отношения (хотя это определенно самый простой и наименее хрупкий путь), вы также можете сделать это процедурно. Наивным подходом было бы запустить метод items для каждой категории и поместить все результаты в один массив, но при этом один запрос на категорию выполнялся бы: печально известная проблема N + 1. Если есть 50 категорий, то это 50 запросов только для получения элементов. Вам лучше всего выполнить один запрос, чтобы найти нужные элементы:

@items = Item.where(:category_id => @categories.map(&:id)).all

(я не полностью уверен, что это синтаксис Arel для классического предложения SQL WHERE…IN, но я думаю, что это так.)

@categories.map(&:id) возвращает массив идентификаторов всех категорий, который передается как условие для category_id элемента. Итак, на английском языке: «найти все элементы, где category_id находится в этом списке идентификаторов категории»

Итак, есть два решения с одним запросом, которые работают примерно одинаково хорошо. Перейти на тот, который чувствует себя чище для вас:)

2 голосов
/ 29 марта 2011

Попробуйте это:

@categories.map(&:items)
1 голос
/ 29 марта 2011

Это не работает, потому что @categories - это массив, а не объект категории. Вы можете сделать:

items = []
@categories.each do |category|
  items = items.concat(category.items)
end
1 голос
/ 29 марта 2011

@categories - это массив Category элементов, но функция связывания не существует в самом массиве.Вам нужно перебрать массив категорий и собрать связанные элементы:

@items = @categories.map(&:items).flatten

map само по себе вернет массив массивов, каждый из которых соответствует выводу category.items, поэтому вам нужно вызватьflatten для создания одного массива элементов.

Это решение вашей непосредственной проблемы, но пост @ Matchu - это то, как вы должны написать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...