STIとポリモーフィック関連の整理
概要
STIとポリモーフィック関連の理解が混同していたので改めて整理した記事。
STIとは
1つのテーブルを継承して複数のモデルを表現する形式。
具体例
carsテーブルとtrainsテーブルがvehiclesテーブルを継承すると仮定する。
クラス間の関係性は下図のようになる。

STIはテーブル一つで表現するため、DBに存在するテーブルはvehiclesテーブルのみ。

vehiclesテーブルのtypeカラムを使って、trains or carsの判別をする。
メリット
- テーブルが増えない
- Railsの場合だとSTIをサポートしているので実装容易性がある
- サブクラスのレコードを取得するためにJOINする必要が無い
デメリット
- カラム数が多くなる
- 別のサブクラスで利用しなければnull値が増える
- 特定のサブクラスのみを参照すべき他テーブルの外部キー制約が、誤ったサブクラスを参照することを防げない
参考
みんなRailsのSTIを誤解してないか!? - Qiita この記事はfreee Engineers Advent Calendar 2016の4 日目です。 こんにちは、freeeでエンジニアをやっている @yebihara です。 今日はRailsの単一テーブル継承/Single Table Inheritance(以下STI)... Qiita
ポリモーフィック関連とは
複数のモデルから同じモデルを参照する際の関連付けの仕組み。
多態性という言葉より複数のモデルに対して共通のインターフェースを設けられる。
Active Record Associations — Ruby on Rails Guides This guide covers the association features of Active Record.After reading this guide, you will know how to: Understand the various types of associations. Declare associations between Active Record models. Choose the right association type for your models. Use Single Table Inheritance. Setting up and using Delegated Types. Ruby on Rails Guides具体例
ProductモデルとEmployeeモデルはPictureモデルを参照すると仮定(railsガイドそのまま)
class Picture < ApplicationRecord
belongs_to :imageable, polymorphic: true
end
class Employee < ApplicationRecord
has_many :pictures, as: :imageable
end
class Product < ApplicationRecord
has_many :pictures, as: :imageable
endpicturesテーブルには参照元の親テーブルを表すカラム(imageable_id / imageable_type)を持たせる。
class CreatePictures < ActiveRecord::Migration[7.0]
def change
create_table :pictures do |t|
t.string :name
t.bigint :imageable_id
t.string :imageable_type
t.timestamps
end
add_index :pictures, [:imageable_type, :imageable_id]
end
end@picture.imageableを介して親テーブルにアクセスできる。
@pictureがどの親に紐づいているかどうかの分岐が必要ない。(typeによる分岐等)
メリット
- DRYに書ける
- 中間テーブルを省いて相互に関連付けが可能
- 共通インターフェースで関連付けが可能
デメリット
- 外部キーを貼れないので参照整合性制約が担保されない
まとめ
ポリモーフィックとSTIの言語の意味を考えると自然とどちらか分かる。
言語の意味をしっかり抑えようと思った。