概要
STIとポリモーフィック関連の理解が混同していたので改めて整理した記事。
STIとは
1つのテーブルを継承して複数のモデルを表現する形式。
具体例
carsテーブルとtrainsテーブルがvehiclesテーブルを継承すると仮定する。
クラス間の関係性は下図のようになる。
STIはテーブル一つで表現するため、DBに存在するテーブルはvehiclesテーブルのみ。
vehiclesテーブルのtypeカラムを使って、trains or carsの判別をする。
メリット
- テーブルが増えない
- Railsの場合だとSTIをサポートしているので実装容易性がある
- サブクラスのレコードを取得するためにJOINする必要が無い
デメリット
- カラム数が多くなる
- 別のサブクラスで利用しなければnull値が増える
- 特定のサブクラスのみを参照すべき他テーブルの外部キー制約が、誤ったサブクラスを参照することを防げない
参考
https://qiita.com/yebihara/items/9ecb838893ad99be0561
ポリモーフィック関連とは
複数のモデルから同じモデルを参照する際の関連付けの仕組み。
多態性という言葉より複数のモデルに対して共通のインターフェースを設けられる。
https://guides.rubyonrails.org/association_basics.html#polymorphic-associations
具体例
ProductモデルとEmployeeモデルはPictureモデルを参照すると仮定(railsガイドそのまま)
1class Picture < ApplicationRecord 2 belongs_to :imageable, polymorphic: true 3end 4 5class Employee < ApplicationRecord 6 has_many :pictures, as: :imageable 7end 8 9class Product < ApplicationRecord 10 has_many :pictures, as: :imageable 11end
picturesテーブルには参照元の親テーブルを表すカラム(imageable_id
/ imageable_type
)を持たせる。
1class CreatePictures < ActiveRecord::Migration[7.0] 2 def change 3 create_table :pictures do |t| 4 t.string :name 5 t.bigint :imageable_id 6 t.string :imageable_type 7 t.timestamps 8 end 9 add_index :pictures, [:imageable_type, :imageable_id] 10 end 11end
@picture.imageable
を介して親テーブルにアクセスできる。
@picture
がどの親に紐づいているかどうかの分岐が必要ない。(typeによる分岐等)
メリット
- DRYに書ける
- 中間テーブルを省いて相互に関連付けが可能
- 共通インターフェースで関連付けが可能
デメリット
- 外部キーを貼れないので参照整合性制約が担保されない
まとめ
ポリモーフィックとSTIの言語の意味を考えると自然とどちらか分かる。
言語の意味をしっかり抑えようと思った。