🍇

STIとポリモーフィック関連について調べてみた

2023/04/02に公開

STIとは?

1つのテーブルを複数のModel間で共有するというものです。
複数のModelのクラス名がtypeというカラムに入ります。

例として車を挙げてみます。
まず、ベースとなるCarモデルを作成します。

# app/models/car.rb
class Car < ApplicationRecord
end

DBのCarテーブルは以下のカラムを持っています。

id       ...ID
type     ...車種
price    ...価格
capacity ...収容人数

それでは、Carモデルを継承する車種ごとのモデルを作ってみます。

# app/models/hoge_car.rb
class HogeCar < Car
end

# app/models/fuga_car.rb
class FugaCar < Car
end

# app/models/honya_car.rb
class HonyaCar < Car
end

それぞれのModelはCarテーブルと紐づいているので、
当然フィールドはCarテーブルのものと同じものになります。
つまり、Carと同じフィールドを持った、車種ごとのモデルが出来上がりました。

それでは、Carをインスタンス化してみます。

Car.new(price: 1000, capacity: 1)
=> #Car<type: Nil> # TODO 修正

次に、HogeCarをインスタンス化してみます。

HogeCar.new(price: 2000, capacity: 2)
=> #Car<type: HogeCar> # TODO 修正

こんな感じで、ベースのCarモデルをインスタンス化すると、typeにはnilが入り、
Carモデルを継承している車種ごとのモデルをインスタンス化すると、typeにはクラス名が入ります。

id|      type| price| capacity|
 1|      NULL|  1000|        1|
 2|   HogeCar|  2000|        2|
 3|   FugaCar|  3000|        4|
 4|  HonyaCar|  5000|        8|

同じフィールド、同じ振る舞いをするけれど、
それぞれのメソッドの戻り値など中身が異なる場合に使うことができます。

STIの使い方

STIは、

  • typeカラムを定義する
  • 継承されるModelと継承するModelを定義する

1つのテーブルをタイプ別に分けることができる=バリデーションとかも自由に変えれる

参考
https://railsguides.jp/autoloading_and_reloading_constants.html#sti(単一テーブル継承)

ポリモーフィック関連とは?

  • 一つのModelを複数のModel間で共有するというもの
  • 共有できない場合は、複数のModelそれぞれの関連付けのためのカラムが増えてしまう

参考
https://railsguides.jp/association_basics.html#ポリモーフィック関連付け
https://qiita.com/itkrt2y/items/32ad1512fce1bf90c20b#ポリモーフィックの説明その前に

まとめ

一回自分の中で整理してみると、全く別物だなーとなって、
なぜこの2つが比較されたりしてるのかがわからなくなってしまいました。

ざっくり整理するとこんな感じなのかなぁと思います。

STI

  • 1つのテーブルを複数のModel間で共有するというもの

ポリモーフィック関連

  • 1つのModelを複数のModel間で共有するというもの

Discussion