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

时间:2015-01-15 20:30:06

标签: sql ruby-on-rails ruby activerecord

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

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 个答案:

答案 0 :(得分:1)

由于您的category_id表格中没有items列,因此您需要加入范围中的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

那应该整理一下。