Rails 数据库设置多态性

Rails database setup Polymorphism

我们必须创建一个请求系统,其中包含大约 10 种不同类型的请求。所有这些请求都属于我们应用程序的 'accounting' 方面。因此我们称它们为 "Accounting requests"。

所有请求可能只共享几列,每个请求最多有 20 列。

我们开始怀疑,当我们开始不得不进行非常复杂的连接或查询时,例如,将所有请求类型提取到单个 table 然后对其进行排序。

也许只使用单一 Table 继承会更容易,因为它将有一个类型列,我们将使用一个 table 来存储所有 10 种会计请求类型。

您如何看待将 STI 用于如此多的多态关联和需求?

基本上,它会有这样的模型:

AccountingRequest
BillingRequest < AccountingRequest
CheckRequest < AccountingRequest
CancellationRequest < AccountingRequest

每个子类大约有 10 多个字段。


目前正在阅读有关多重 Table 继承 here 的内容。在这种情况下,这似乎是符合我要求的解决方案。虽然还不确定。

听起来可行。

当我对此进行调查时,我发现广泛使用值对象有助于控制某些属性对某些类型的不适用性。

在我的例子中,我有多种类型的产品,例如,其中一些没有特定的尺寸。在那些情况下,我在适当的地方使用空对象来指示 "Not applicable"。

编辑:我还发现 composed_of 语法非常方便:https://apidock.com/rails/ActiveRecord/Aggregations/ClassMethods/composed_of

您可以在那种情况下使用 STI。但是制作 STI 需要将所有列合并为一个 table,这不是一个好主意。 table 的字段数会很大。

我认为你应该像下面这样分成两个 tables...

  1. 请求:请求table将是保存请求类型信息的多态table。

  2. RequestItem:请求项table会将所有20个字段记录保存到table中,并且会有一个请求的外键table。请求项 table 将在数据库中有两个字段,称为键和值。

目前我在这种情况下使用了一些 NoSQL。 Postgresql's JSONB 类型允许存储多级 ruby 哈希。它还提供了丰富的功能:数据库级约束、索引和查询运算符。

因此,通用属性以标准方式存储,并且 child 特定 - 在 jsonb 中。然后您可以在此基础上使用您需要的任何东西:STI、值 Objects 模式、序列化或只是为每个 child 创建范围。我更喜欢最后一个——我的模型很薄,大多数约束都是数据库级别的,所有业务逻辑都在服务中 类。

优点:

  1. 在需要添加一个 child 类型时避免 alter table 在大表上
  2. 保持我的查询高效
  3. 防止存储和选择不必要的列
  4. JSON API 的开箱即用序列化

缺点:

  1. 有点无模式
  2. 供应商锁定

如果您的模型都具有相同的属性,则 STI 非常适合。

但是,如果您的子 类 开始具有特定于它们的属性而不适用于其他属性,则 STI 可能会导致大量空列。在那种情况下,我通常更喜欢使用多态关联。

这一 railscast 集很好地说明了 2

之间的区别