tawara's blog

雑記。個人の見解です。

ポリモーフィック関連を使うと、複数のモデルに属していることを1つの関連付けで表現できる

こんにちは、たわらです。

ポリモーフィック関連について整理した記事です。

モデルのコードはこんな感じ

ブログ記事を作成するサービスを考えます。記事をブロックを追加するかたちで作成します。記事は、Ariticleブロックを複数持っているということです。そして、記事ブロックには3種類あります。文章と画像です。

SentenceモデルとMediumモデルがあり、それらにAriticleblockモデルがポリモーフィック関連しているとします。

それぞれこんなふうになります。

Ariticleblockモデル

class ArticleBlock < ApplicationRecord
  belongs_to :article
  belongs_to :blockable, polymorphic: true, dependent: :destroy
  # ...
end

Sentenceモデル

class Sentence < ApplicationRecord
  has_one :article_block, as: :blockable, dependent: :destroy
  # ...
end

Mediumモデル

class Medium < ApplicationRecord
  has_one :article_block, as: :blockable, dependent: :destroy
  # ...
end

Articleblockモデルにpolymorphic: trueとあります。これでポリモーフィック関連ができます。blockableという存在しないテーブル名に属している、と読めます。

SentenceモデルとMediumモデルにはas: :blockableとあります。Articleblockモデルにblockableとして関連する、と読めます。

カラムの作成はこんな感じ

Ariticleブロックのカラムにはポリモーフィック関連のための準備が必要です。

class CreateArticleBlocks < ActiveRecord::Migration[5.2]
  def change
    create_table :article_blocks do |t|
      t.belongs_to :article
      t.belongs_to :blockable, polymorphic: true
      t.timestamps

      t.index :level
    end
  end
end

〇〇ableを作成する必要があるようです。

こうすると自動的にAriticleblockテーブルに、blockable_idとblockable_typeが追加されます。

この状態で、Sentence.newをすると自動的に、blockable_idに適当な数値が入り、blockable_typeに"Sentence"と入ります。

コンソールでの出力はこんな感じ

[1] pry(main)> ArticleBlock.first
  ArticleBlock Load (1.7ms)  SELECT  `article_blocks`.* FROM `article_blocks` ORDER BY `article_blocks`.`id` ASC LIMIT 1
=> #<ArticleBlock:0x00007ffa2e9d37f0
 id: 1,
 article_id: 1,
 blockable_type: "Sentence",
 blockable_id: 1,
 created_at: Wed, 15 Jul 2020 16:43:32 JST +09:00,
 updated_at: Wed, 15 Jul 2020 16:43:32 JST +09:00>
[2] pry(main)> ArticleBlock.first.blockable
  ArticleBlock Load (0.6ms)  SELECT  `article_blocks`.* FROM `article_blocks` ORDER BY `article_blocks`.`id` ASC LIMIT 1
  Sentence Load (1.2ms)  SELECT  `sentences`.* FROM `sentences` WHERE `sentences`.`id` = 1 LIMIT 1
=> #<Sentence:0x00007ffa2eaa9fd0 id: 1, body: "<p>およよよよ</p>", created_at: Wed, 15 Jul 2020 16:43:32 JST +09:00, updated_at: Wed, 15 Jul 2020 16:43:46 JST +09:00>

参考文献リスト

railsguides.jp

Railsのポリモーフィック関連とはなんなのか - Qiita

ポリモーフィック関連覚え書き - Qiita