7
1

More than 1 year has passed since last update.

RailsのSTI / CTI / CCI

Last updated at Posted at 2022-01-26

STI / CTI / CCI

STI = Single Table Inheritance/単一テーブル継承
CTI = Class Table Inheritance / クラステーブル継承
CCI = Concrete Class Inheritance / 具象クラス継承

エンタープライズアプリケーションアーキテクチャパターンで触れられている、オブジェクト指向で設計されたスーパークラス / サブクラスからなる継承関係をリレーショナルデータベースのテーブルとして実装する 3 つのパターン。

Model

抽象クラスとしての Animal モデルに対して、具象クラスとして Dog / Cat / Bird が存在する。

class Animal < ActiveRecord::Base
end
class Dog < Animal
end
class Cat < Animal
end
class Bird < Animal
end

STI

STI(Single Table Inheritance/単一テーブル継承) は、単一の継承階層に所属するクラス群を、ただひとつのテーブルを使って永続化する手法。
複数のモデルで 1 つのテーブルを共有する。

ほげ.png

Dog / Cat / Bird  というテーブルは存在せず、全てのデータは Animals に保存される。
Rails では標準で STI がサポートされており、type というカラムでモデルを判別する。

Rails では、ActiveRecord が STI の時に type という名前を予約語として使用するので意図せずエラーが発生することがある。
STI を使用しない時や、STI を使用する際に type ではないカラムでモデルを判別したい場合には以下のようにする。

class Animal < ActiveRecord::Base
  # 無効にする
  self.inheritance_column = :_type_disabled
  # 変更する
  self.inheritance_column = :kind
end

長所

  • 必要なテーブルは 1 つだけで、サブクラスが増えてもテーブルが増えない
  • 論理的なレコード全体(ここでは Animal 全体)を取得するためにジョインが必要ない
  • Rails でネイティブサポートされている

短所

  • 一部のサブクラスでしか使用されないカラムがある場合、他のクラスでは null になる
  • そのため、NotNull 制約をかけることができない

CTI

CTI(Class Table Inheritance/クラステーブル継承)では、抽象クラスと具象クラスのテーブルを全て作成する。
テーブルは、親モデルへ関連づけを行うためのカラムと、そのクラス自身とサブクラスに固有の共通属性のためのカラムのみを持つ。
cti.png

長所

  • STI のように NULL の問題が発生しない

短所

  • 具象クラスが増えるとテーブルが増える
  • 論理的なレコード全体を取得するためにジョインが必要

CCI

CCI(Concrete Class Inheritance/具象クラス継承)では、具象クラスのテーブルのみを作成する。
テーブルは、抽象クラスから継承する共通属性も含めて、その具象クラスが持つ全ての属性のためのカラムを持つ。

CCI.png

長所

  • STI のように NULL の問題が発生しない

短所

  • 具象クラスが増えるとテーブルが増える
7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1