単一テーブル継承 type{}

2021.5.18

課題4でのFactoryBotのtypeが何なのか理解したい。

参照

【Rails】単一テーブル継承(STI)について - Qiita

 

(spec/factories/categories.rb)

FactoryBot.define do
factory :category do
type { 'Category' } #ここの部分
sequence(:name) { |n| "応用課題#{n}" }
sequence(:slug) { |n| "ouyou-kadai#{n}" }
end
end

 

「type」 

モデルでSTI(Single Table Inheritance)を指定する場合に追加する。

Active Recordは、デフォルトで「type」という名前の列にクラス名を格納することで継承を許可する。

参照

Active Record の基礎 - Railsガイド

ActiveRecord::Inheritance

 

単一テーブル継承(STI)とは

STI(Single Table Inheritance)

同じカラムの設計のテーブルを一つにまとめて、継承することで余計なテーブルを増やさず、DRYなテーブルに設計するというもの。

考え方はクラスの継承と同じ感じ!

イメージは参照のブログがとてもわかりやすい

 

 STI不使用(通常テーブル設計)

STI不使用.png

Authors、categorys、tags3つとも同じカラム設計なのにテーブルをそれぞれ作成しているのは可読性が下がるし、無駄。

 STI使用

STI使用.png

図にも書いてある通り、authors、category、tagsは擬似テーブルであり、DBには実在しないテーブルになります。
実在しないので、データは全てtaxonomiesに保管されます。

参照

【Rails】単一テーブル継承(STI)について - Qiita

 

ポイント

参照の図はDBレベルでの相関図。混乱するので、DBとModelは切り分けて考える。

❶Modelレベルでは、Article.rbなどをみるとわかるが、Author,Category,Tag(Article tagsを介して)直接アソシエーションが組まれている。

ArticleとTaxonomyは各Modelファイルを見るとアソシエーションは組まれていない。

❸擬似テーブル3つは継承元がApplicationRecordを継承したTaxonomyになっている。

 

❶課題4の(app/models/article.rb)

class Article < ApplicationRecord
belongs_to :category
belongs_to :author

has_many :article_tags
has_many :tags, through: :article_tags

❷(app/models/taxonomy.rb)

class Taxonomy < ApplicationRecord
validates :name, presence: true, uniqueness: { scope: :type }, length: { maximum: 16 }
validates :slug, presence: true, uniqueness: { scope: :type }, length: { maximum: 64 }, slug_format: true
end

❸(app/models/taxonomy.rb)

class Taxonomy < ApplicationRecord
validates :name, presence: true, uniqueness: { scope: :type }, length: { maximum: 16 }
validates :slug, presence: true, uniqueness: { scope: :type }, length: { maximum: 64 }, slug_format: true
end

(app/models/author.rb)

class Author < Taxonomy
has_many :articles

has_one_attached :avatar

validates :avatar, attachment: { purge: true, content_type: %r{\Aimage/(png|jpeg)\Z}, maximum: 10_485_760 }
end

(app/models/category.rb)

class Category < Taxonomy
has_many :articles
end

(app/models/tag.rb)

class Tag < Taxonomy
has_many :article_tags
has_many :articles, through: :article_tags
end

 

Active Recordについても確認して方がいい点があるので、参照ページを確認する。