单一 Table 继承 - 附加 Class 名称

Single Table Inheritance - Additional Class Name

我的 Rails 4 应用程序有一个情况,我有 STI 并且想通过额外的 type.

自定义默认查询

类:

class Candidate < ApplicationRecord
end

class Candidate::Site < Candidate
end

现在,如果我进行查询,我得到的结果如下:

> Candidate::Site.count
# SELECT COUNT(*) FROM "candidates" WHERE "candidates"."type" IN ('Candidate::Site')
=> 0

现在,在我的情况下,我想添加一个额外的 type 每次都应该查找的查询。通过利用 IN 子句,我预期要触发的查询是:

SELECT COUNT(*) FROM "candidates" WHERE "candidates"."type" IN ('Candidate::Site', 'Site')

有人可以帮我控制这里的 IN 子句吗?提前致谢。

您可以这样查询:

Candidate.where(
  Candidate.inheritance_column => [Candidate::Site, Site, SomeOtherClass].map(&:sti_name)
).count

在详细研究并深入研究 Rails STI 源代码后,我发现我的方案需要覆盖 Rails 的默认 STI。以下是我实现目标所需的条件:


class Candidate::Site

  # To enable renaming of Site to Candidate::Site
  # per ENG-9551, we need to:
  # 1. disable the 'type' column from using Rails' built-in STI
  self.inheritance_column = :_nonexistant_column_to_bypass_sti

  # 2. manually set the type column to Candidate::Site when we save,
  # so that new and edited records are saved as Candidate::Site
  before_save { self.type = 'Candidate::Site' }

  # 3. always report the type as a Candidate::Site
  def type
    'Candidate::Site'
  end

  # 4. and set a default scope which only reads type columns that are
  # 'Candidate::Site' or 'Site' so that STI
  # still appears to be the same as always
  default_scope { where(type: 'Candidate::Site').or(where(type: 'Site')) }

  ...
  ...
  ...
end

因此,现在使用 Candidate::Site.create 创建的任何新记录都将存储类型 Candidate::Site,而查询将使用默认范围并同时考虑类型 Candidate::SiteSite.