Inheritance 单表继承

单表继承 一个或多个 Model 继承于另一个 Model,并且最终它们用的是同一张表。

我们会遇到这样的情况:

Employee 有 manager 和 developer Computer 有 pc 和 mac

有时候,需要把它区分对待;有时候,又要对它们一视同仁。

设计表和 model 时,用得比较多的是"两张类似的表,两个类似的 model" 还是 "一张表,一个 model,一个用于标识的字段",再或者是第 3 种选择,也就是这里要讲的"STI(单表继承)"。

一般说来,单表继承通常用于:属性一样,但行为不一致。

是什么?

单表,就是在数据库你只需要一张表。 继承,就是你的 model 之间存在着继承关系。

上面的例子中: 我们可以只用 employees 表,却有 model Manager 和 model Developer,它们都继承于 Employee. 我们可以只用 computers 表,却有 model Pc 和 model Mac,它们都继承于 Computer.

选择

  1. 各子模块属性是一样的。这里要从"面向对象"的角度去看,而不是简单的'属性一样'就能使用。

  2. 需要把这些子模块代表的数据放在一想显示或者说做聚合吗?如果需要的话,那么使用 STI 是比较好的选择。因为从性能上来说,即使优化做得再好,跨表操作,也不如在一个表里操作,来得简单、高效。

  3. 和第 1 条有点类似,它们属性是一样的,只是行为不一致而矣。如果只是大部分属性一样,那么可以考虑一下"多态关联"。

实际使用过程中,单表继承在某些方面提供了方便(比如:自动设置 type),但同时也会造成麻烦(比如:多个 model)。同样的,使用"两张类似的表,两个类似的 model" 或 "一张表,一个 model,一个用于标识的字段"或其它手段,也会有自己的问题。

这些方法都有利有弊,选择时,我们尽量选择利大于弊的那一种吧。

使用

单表继承默认使用 type 做为标识字段,在表里面新增字段即可,当然,也可以用【Model Schema】里的 inheritance_column 自定义标识字段。创建相应对象时,会根据所使用的模块名自动设置它的值。

class Company < ActiveRecord::Base
  # ...
end

class Firm < Company
  # ...
end

class Client < Company
  # ...
end

最后更新于