在has_many Association

时间:2016-01-24 23:19:23

标签: ruby-on-rails activerecord rails-activerecord

说我有以下型号:

class Category < ActiveRecord::Base
    has_and_belongs_to_many :items
end

class Item < ActiveRecord::Base
    has_and_belongs_to_many :categories
end

我正在构建一个端点,用于检索所有项目,其中每个项目应与其所属的类别ID数组相关联。示例结果将是:

[
    {
        name: 'My Item',
        category_ids: [1, 2, 3]
    },
    // more items...
]

通过这种配置,我可以在每条记录上调用item.category_ids,从而产生我想要的SQL,看起来像SELECT categories.id FROM categories INNER JOIN categories_items ... WHERE categories_items.item_id = $1

然而,这显然会导致N + 1 - 而且我似乎无法在急切的负载中找到一种方法来做到这一点。我想要做的是获取一个项目列表,只是他们所在类别的ID,急切加载每个category_ids字段Item (但是,如果有另一种方法可以使用急切加载来完成相同的操作,我也可以使用它)

编辑以解释与副本的区别:

我正在寻找是否可以在两个单独的查询中执行两个操作。一个获取项目,一个获取类别ID。 items表相对较宽,我不希望将每个项目所包含的类别数返回的行数相乘 - 如果可能的话。

1 个答案:

答案 0 :(得分:1)

使用连接模型而不是has_and_belongs_to_many将允许您直接查询连接表(无需自己破解查询):

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

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

class ItemCategory
  belongs_to :item
  belongs_to :category
end

请注意,has_many through:的表格命名方案不同 - 而不是items_categoriesitem_categories。这样,常量查找将正常工作(否则rails会查找Items::Category作为连接模型!) - 因此您需要迁移才能重命名该表。

items = Item.all
category_ids = ItemCategory.where(item_id: items.ids).pluck(:category_id)