Rails ActiveRecord 连接多个表

Rails ActiveRecord joins with multiple tables

我有一个类别模型,它通过第三个模型 OfferCategory 属于 Offer 模型。我也有一个类似的 PlumCake 模型关联,它通过 PlumCakeCategory 模型关联到类别模型。

类别:

has_many :offer_categories, dependent: :destroy, inverse_of: :category
has_many :offers, through: :offer_categories, source: :offer
has_many :plum_cake_categories, dependent: :destroy, inverse_of: :category
has_many :plum_cakes, through: :plum_cake_categories, source: :plum_cake

报价:

has_many :offer_categories, dependent: :destroy, inverse_of: :offer
has_many :categories, through: :offer_categories, source: :category, dependent: :destroy

报价类别:

belongs_to :offer
belongs_to :category

李子蛋糕:

 has_many :plum_cake_categories, dependent: :destroy, inverse_of: :plum_cake
has_many :categories, through: :plum_cake_categories, source: :category, dependent: :destroy

梅子蛋糕类别:

belongs_to :plum_cake
belongs_to :category

以及 category/plumcakes 的类似关联。

现在我想获取所选优惠和李子蛋糕的所有类别。以下查询为我提供了 eligible_offer_ids 提供的类别列表。

Category.joins(:offer_categories).where(offer_categories: { offer_id: eligible_offer_ids })

我可以为 plum_cake 触发类似的查询并获取这两个查询的唯一类别。

cat1 = Category.joins(:offer_categories).where(offer_categories: { offer_id: eligible_offer_ids })
cat2 = Category.joins(:plum_cake_categories).where(plum_cake_categories: { plum_cake_id: eligible_plum_cake_ids })
(cat1 + cat2).uniq

但是有没有办法在单个查询中得到相同的结果 ((cat1 + cat2).uniq)?

我认为如果您使用 rails STI(单一 table 继承),您可以轻松实现您的功能。

如果您的结构如下所示:

class Category
  has_many :offer_categories, dependent: :destroy, inverse_of: :category
  has_many :offers, through: :offer_categories, source: :offer
  has_many :plum_cake_categories, dependent: :destroy, inverse_of: :category
  has_many :plum_cakes, through: :plum_cake_categories, source: :plum_cake
  has_many :sub_categories
end

class SubCategory
  belongs_to :offer
  belongs_to :plum_cake
  belongs_to :category
end

class OfferCategory < SubCategory
  validate_presence_of :offer_id
end

class PlumCakeCategory < SubCategory
  validate_presence_of :plum_cake_id
end

您的查询将是:

Category.joins(:sub_categories).where(sub_categories: { offer_id: eligible_offer_ids }).or(Category.joins(:sub_categories).where(sub_categories: { plum_cake_id: eligible_plum_cake_ids }))

STI documentation

如果您不想更改结构:

Category.left_outer_joins(:offer_categories, :plum_cake_categories).where(offer_categories: { offer_id: eligible_offer_ids }).or(Category.left_outer_joins(:offer_categories, :plum_cake_categories).where(plum_cake_categories: { plum_cake_id: eligible_plum_cake_ids })).uniq