ポリモーフィック関連

ポリモーフィック関連付けにより、一つのモデルと複数のモデルを関連付けすることができる。

例としてArticleBlockモデルに複数のモデル(Sentence, Medium, Embed)を関連付ける。

マイグレーションの作成。

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.integer :level, default: 0, null: false
      t.timestamps

      t.index :level
    end
  end
end


モデルの設定。

# article_block.rb

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

class Sentence < ApplicationRecord
  has_one :article_block, as: :blockable, dependent: :destroy
  has_one :article, through: :article_block
  # ...
end
# medium.rb

class Medium < ApplicationRecord
  has_one :article_block, as: :blockable, dependent: :destroy
  has_one :article, through: :article_block
  # ...
end
# embed.rb

class Embed < ApplicationRecord
  has_one :article_block, as: :blockable, dependent: :destroy
  has_one :article, through: :article_block
  # ...
end


これによりArticleBlockからSentence, Medium, Embedを呼び出すことが可能となった。

ArticleBlock.first.blockable


逆にSentence, Medium, EmbedからArticleBlockを呼び出すことも可能である。

Sentence.first.article_block


さらにArticleArticleBlockを介してSentence, Medium, Embedを関連付けることでArticleからSentence, Medium, Embedを呼び出せるようになる。

# article.rb

class Article < ApplicationRecord
  has_many :article_blocks, -> { order(:level) },
           inverse_of: :article
  has_many :sentences, through: :article_blocks,
                        source: :blockable, source_type: 'Sentence'
  has_many :media, through: :article_blocks,
                    source: :blockable, source_type: 'Medium'
  has_many :embeds, through: :article_blocks,
                     source: :blockable, source_type: 'Embed'
  # ...
end


Article.first.media
Embed.first.article



参考記事:【初心者向け】Railsのポリモーフィック関連付けを理解しよう - Qiita