Rails - 预加载 has_many :通过关联条件

Rails - eager load has_many :through with condition on association

假设我有一个 Item 模型和具有 has_many :through 关联的 Category 模型:

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

现在,我想要一个项目范围,它将获得特定类别的所有处于特定状态(假设它具有状态属性)的项目。例如:获取所有状态为 "in stock" 且属于 id = 3 类别的项目,例如: scope :in_stock_for_category, ->(category) { where(status: SOME_ENUMERATED_VALUE) .... 我遗漏了将结果集限制为特定类别的查询的最后一部分。

谢谢!

由于您的 items table 中没有 category_id 列,您需要在范围中加入 category_itemscateogeries在指定特定类别的 ID 条件之前。

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

那应该收拾东西了。