2015-01-15 2 views
0

Допустим, у меня есть Item модель и Category модель с has_many :through ассоциации:Rails - нетерпеливый has_many нагрузки: через с условием об ассоциации

class Item < ActiveRecord::Base 
    has_many :category_items 
    has_many :categories, through: category_items 
end 

class Category < ActiveRecord::Base 
    has_many :category_items 
    has_many :items, through: category_items 
end 

class CategoryItems < ActiveRecord::Base 
    belongs_to :category 
    belongs_to :items 
end 

теперь, я хочу, чтобы иметь объем по пунктам, которые будут получать все элементы которые имеют определенный статус (предположим, что он имеет атрибут статуса) для конкретной категории. например: получить все элементы со статусом «на складе» и который относится к категории с id = 3, что-то вроде: scope :in_stock_for_category, ->(category) { where(status: SOME_ENUMERATED_VALUE) .... Мне не хватает последней части запроса, чтобы ограничить набор результатов определенной категорией.

Спасибо!

ответ

1

Поскольку вы не имеете category_id столбца в вашей items таблицы, вам необходимо присоединиться к любому category_items или cateogeries в Вашей области, прежде чем можно указать идентификатор состояние определенной категории в.

class Item < ActiveRecord::Base 
    scope :in_stock_for_category, -> do |category| 
    joins(:category_items). 
    where(category_items: {category_id: category.id}). 
    where(items: {status: SOME_ENUMERATED_VALUE}). 
    group("items.id") # grouping might be unnecessary since you're adding the where condition for the category's id 
    end 
end 

Это будет работать. Или, если вы хотите присоединиться к categories, сделайте следующее:

class Item < ActiveRecord::Base 
    scope :in_stock_for_category, -> do |category| 
    joins(:categories). 
    where(categories: {id: category.id}). 
    where(items: {status: SOME_ENUMERATED_VALUE}). 
    group("items.id") # grouping might be unnecessary since you're adding the where condition for the category's id 
    end 
end 

Если у вас уже есть category однако, это может быть полезно создать has_many отношения на предметы, которые имеют определенный статус. Что-то вроде следующего:

class Category < ActiveRecord::Base 
    has_many :in_stock_items, -> do 
    where(items: {status: SOME_ENUMERATED_VALUE}) 
    end, through: :category_items, source: :item 
end 

Кроме того, если у вас есть рамки статуса в Item (что-то вроде scope :in_stock, -> { where(status: SOME_ENUMERATED_VALUE) }), вы можете скорее всего, изменить выше has_many отношения к следующим:

class Category < ActiveRecord::Base 
    has_many :in_stock_items, -> do 
    merge(Item.in_stock) # http://apidock.com/rails/ActiveRecord/SpawnMethods/merge 
    end, through: :category_items, source: :item 
end 

Это должно аккуратные вещи.

+0

Большое спасибо! отличный ответ. –

+0

BTW - это 'group (" items.id ")' требуется здесь? Какова цель этого? –

+0

После 'joins' может быть несколько строк, которые имеют один и тот же элемент, потому что элемент может иметь много категорий. Сгруппировав результаты с помощью 'items.id', вы гарантируете, что вы получите один элемент за строку. – Humza

Смежные вопросы