Post

単一テーブル継承(STI)について

応用篇でのtaxonomiesテーブルは何なんだって気になってて、調べてみたら、単一テーブル継承(STI)で使ってるテーブルのことがわかった。

同じ親クラスから継承している複数の子モデルの情報は各自のテーブルではなく、全てを親モデルのテーブルに記入する。
各子モデルの情報はtypeコラムで標識する。

今回はauthor, category, tagの三つのモデルの情報をtaxonomiesテーブルに記入している
どのモデルの情報かを標識するため、モデル名をtypeコラムに記入する。
それで、三つのテーブルそれぞれ作成するのが不要になる。

本当はDBには一つの集約テーブルしか存在しないけど、
レコードを取得するとき、それぞれのテーブルが存在するかのように扱える
例えば、authorのレコードを全部取得するなら、普通にAuthor.allでいける。
実際に発行するSQL文はSELECT "taxonomies".* FROM "taxonomies" WHERE "taxonomies"."type" IN ('Author')

ただ現場ではSTIはあまり活用されていないようで、qiitaで向き不向きの議論があった

  • 単純にtypeフィールドが文字列で入るので空間効率が良くない。とくにレコード件数が数億件を超えるような時系列テーブルになると、この反復は無視できない
  • STIとして実装したサブクラスには独自メソッドが1個か2個しかないようなケースも多く、ほとんどが共通の処理で、このような場合にはサブクラスの定義ファイルが分割されてしまうのはかえって見通しを悪くしてしまい
  • 多段継承がない場合、enumで処理の異なる部分だけを分岐してやったほうが、全体としてコピペも減り、フローも追いやすくなる
  • サードパーティのgemがSTIでの利用を考慮していないため、実装上うまくいかなくて、そのgemの利用が無理になったケースが多い


それより、今回の場合は、記事のカテゴリやタグと作者は同じクラスから継承していていることは、個人的にちょっと違和感を感じた。

author, category, tagそれぞれnameやslug、descriptionとの共通属性があったため、STIを使ったのか、と思うけど。
現実世界のものから考えると、カテゴリとタグは似たような性質があって、サブクラスとして一緒に扱うのが問題ないかもしれないけど、作者はちょっと違うかなと思った..

参照
シングルテーブル継承 (STI)
クラスの継承(単一テーブル継承)
みんなRailsのSTIを誤解してないか!?

This post is licensed under CC BY 4.0 by the author.