首页 > 解决方案 > 寻求帮助以防止添加包含太多列的表

问题描述

在我的应用程序中Post,我有一个名为 的模型,它与Blog. 这就是他们的样子:

app/models/post

class Post < ApplicationRecord
  belongs_to :blog
end

app/models/blog

class Blog < ApplicationRecord
  has_many :posts
end

该应用程序将收集和存储许多内容管理系统(如 Wordpress)的帖子,并且有些列应该只存在于某些类型的帖子中。我想知道是否有可能有某种层次结构,如下所示:

Post
  - WordpressPost
  - DrupalPost

这很重要,因为这些列应该只在它是 a 时才存在WordpressPost,例如。

我试图理解一种叫做多态关联的东西(我真的做到了),但我就是无法理解这个概念,而且我也不确定这是否会给我带来这种灵活性。

现在posts表格看起来像这样:

+------------+---------------------------------------------------------------------------+------+-----+---------+----------------+
| Field      | Type                                                                      | Null | Key | Default | Extra          |
+------------+---------------------------------------------------------------------------+------+-----+---------+----------------+
| id         | bigint(20)                                                                | NO   | PRI | NULL    | auto_increment |
| site_id    | bigint(20)                                                                | NO   | MUL | NULL    |                |
| status     | enum('auto_draft','draft','future','pending','private','publish','trash') | NO   |     | NULL    |                |
| date       | datetime                                                                  | NO   |     | NULL    |                |
| title      | varchar(255)                                                              | NO   |     | NULL    |                |
| url        | varchar(255)                                                              | NO   |     | NULL    |                |
| body       | longtext                                                                  | NO   |     | NULL    |                |
| created_at | datetime(6)                                                               | NO   |     | NULL    |                |
| updated_at | datetime(6)                                                               | NO   |     | NULL    |                |
+------------+---------------------------------------------------------------------------+------+-----+---------+----------------+

但是像:

- status
- date

应该只存在于 Wordpress 帖子中。我真的很想了解做我想做的事的最佳方式。

谢谢你。

标签: ruby-on-railsrubyactiverecord

解决方案


在将 OO 继承映射到关系数据库时,我们通常有三种方法(如此链接中突出显示的):

  1. 单表继承(STI):一张表,包含所有子类使用的所有属性。这种方式更适合属性从一个子类到另一个子类变化不大的情况。 单表继承示例
  2. 类表继承(MTI):一个具有公共属性的父表,每个子类的子表具有其特定属性和父表的外键。当每个子类甚至不同的关联之间有许多不同的属性时很好。 类表继承示例
  3. 具体表继承:每个类一个表,包含所有需要的属性。如果有很少的共同属性可能会很好。

    具体表继承示例

Rails 允许我们创建单表继承(STI),我们也可以使用具体表继承。但是它没有内置的方式来处理类表继承(以及多表继承 - MTI),这并不妨碍你创建自己的方式,就像它在这个发布

Rails 还允许我们拥有一个多态关联当我们想要为某些记录关联一种类型而为其他记录关联另一种类型时,这很有用,这可以用于继承,但实际上并不是为此而设计的。在此链接中,您将找到所有三种类型的示例以及如何使用它们。


实现它的另一种方法是拥有一个options jsonb field. 当您的字段因一条记录而异时,这是一种很好的方法。这是一种更简单的方法,但必须精心设计,因为可能有一些缺点。


建议的解决方案:

我不会使用:

  • STI:正如您所说,这将是许多不同的管理系统,我认为这不是一个好主意,因为您将有太多未使用的列。
  • Concrete Table Inheritance:我想您希望在进行过程中轻松添加新的管理系统,将它们视为一个系统并忽略它们的细微差别。所以这不是一个好的选择,因为这会使理解它们的共性变得更加困难。

我可以使用:

  • MTI:这将是一个很好的数据库设计,但是当您使用 Rails 时,您必须以自己的方式处理它,这可能会给代码增加一些复杂性。如果我更关心拥有标准化数据库,我会使用它。
  • 多态关联:与MTI相比,会给数据库增加一些复杂性,并且使其可用作继承也会给代码增加一些复杂性。我更喜欢将它与实际的多态关联一起使用。

我会使用:

  • 一个选项 json 字段:我相信您将需要在某些特定时刻访问此特定属性,并且每个不同的管理系统都不会有其他关联。因此,我想这将是最直接的解决方案,同时受到 rails 和数据库的完全支持,而不会增加两者的复杂性。

Ps:如果你只有一些不同的属性,我会用 STI 代替。


推荐阅读