LoginSignup
9
9

More than 3 years have passed since last update.

【Rails】シングルテーブル継承を使って、テーブルの数を削減する【STI】

Last updated at Posted at 2021-01-06

シングルテーブル継承(単一テーブル継承、STI)とは

シングルテーブル継承(以下、STI)は、単一の継承階層に所属するクラス群を、ただひとつのテーブルを使って永続化する手法です。

言葉だけでは伝わリにくいので、下図を御覧ください。

スクリーンショット 2021-01-05 18.49.31.png

Postsテーブル(スーパークラス)が、サブクラスに継承する形になります。
しかし、注意点が2点あります。

  • Books,Clothes,Goodsテーブルは実際には存在しない。
  • 個々のデータは全てスーパークラスのテーブルに保存されます。この場合はPostsテーブル。

それでは、STIはどういう場面で使えばいいのでしょうか。

STI継承しないと中間テーブルが再生産が起きる

私はSTIの存在を知らずにアプリを作っており、下図のようになってしまいました。

スクリーンショット 2021-01-05 18.34.01.png

・・・。

PostsテーブルとしてはBooksとClothesとGoodsの記事を作りたかったのですが。。。

それぞれのテーブルを作ってしまうことで、それぞれの中間テーブル(ここでは、Comments,Likes,Picksテーブル)が再生産が起きてます。

機能自体はできましたが、ゴチャゴチャしすぎて保守的には最悪ですね・・・。
何より新機能をつける度に3つテーブルを用意する必要があり、骨が折れます😅

そこで!STIを使い、Postsクラスをサブクラスに継承させました!
以下の通りです。

スクリーンショット 2021-01-06 13.40.38.png

めっちゃスッキリしましたね!
(画像にはBooks,Clothes,Goodsはテーブルとして書いてありませんが、継承させています。)
これで保守がしやすく、新機能もつけやすくなりました!

やり方(結論)

1. スーパークラスを作る

rails g model postでマイグレーションファイルを作成し、テーブルの設定をします。

migrate/〇〇_create_posts.rb
class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.references :user,foreign_key: true

      #省略

      t.string :type #typeカラムを作成します!
      t.timestamps
    end
  end
end

ここで注意したいことは、typeカラムを作成することです。
この中に継承先のクラス名が入り、管理されます。

2. それぞれのクラスを作成し、スーパークラスを継承させる

先程のファイルをマイグレーションしてできたモデルファイルを編集したものです。

models/post.rb
class Post < ApplicationRecord
  belongs_to :user

  #省略

end

それではrails g model book --parent=Postでbookモデルを作成します。
--parent=PARENTオプションを使うことで、マイグレーションファイルを生成せずに済みます。

models/book.rb
class Book < Post
  #こうすることでスーパークラスのアソシエーションやバリデーションが引き継がれます。
end

完成です!

ちなみに!
この状態でBookモデルを保存すると、Postsテーブルのtypeカラムに"Book"が代入された状態で,Postsテーブルに保存されます。

Book.create(title: "本です",.......)

以上でSTIのやり方は終わりです。
最後まで読んで頂きありがとうございました!

参考

Railsガイド
https://railsguides.jp/association_basics.html

[Rails] STI(単一テーブル継承)とメタプログラミングでDRY
https://qiita.com/kidach1/items/789c2e7aebbcfbd2583e

9
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9