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 つのテーブルを共有する。
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/クラステーブル継承)では、抽象クラスと具象クラスのテーブルを全て作成する。
テーブルは、親モデルへ関連づけを行うためのカラムと、そのクラス自身とサブクラスに固有の共通属性のためのカラムのみを持つ。
長所
- STI のように NULL の問題が発生しない
短所
- 具象クラスが増えるとテーブルが増える
- 論理的なレコード全体を取得するためにジョインが必要
CCI
CCI(Concrete Class Inheritance/具象クラス継承)では、具象クラスのテーブルのみを作成する。
テーブルは、抽象クラスから継承する共通属性も含めて、その具象クラスが持つ全ての属性のためのカラムを持つ。
長所
- STI のように NULL の問題が発生しない
短所
- 具象クラスが増えるとテーブルが増える