🙆‍♀️

Railsでポリモフィック関連を使う方法

2023/08/22に公開

概要

Railsでポリモフィック関連を使う方法を記載します。

使い方

BookとChapterにThoughtをポリモフィック関連で紐づけます。

# frozen_string_literal: true

require 'bundler/inline'

gemfile(true) do
  source 'https://rubygems.org'

  gem 'activerecord', '7.0.7'
  gem 'sqlite3'
end

require 'active_record'
require 'minitest/autorun'
require 'logger'

ActiveRecord::Base.establish_connection(adapter: :sqlite3, database: ':memory:')
ActiveRecord::Base.logger = Logger.new($stdout)

ActiveRecord::Schema.define do
  create_table :books, force: true do |t|
    t.string :name
  end

  create_table :chapters, force: true do |t|
    t.references :book
    t.string :name
  end

  create_table :thoughts do |t|
    t.string :comment
    t.references :thoughtable, polymorphic: true
  end
end

class Book < ActiveRecord::Base
  has_many :chapters
  has_many :thoughts, as: :thoughtable
end

class Chapter < ActiveRecord::Base
  belongs_to :book
  has_many :thoughts, as: :thoughtable
end

class Thought < ActiveRecord::Base
  belongs_to :thoughtable, polymorphic: true
end

class Yakou < Minitest::Test
  def test_yakou
    yakou = Book.new(name: '夜行')
    yakou.chapters = %w[尾道 奥飛騨 津軽 天竜峡 鞍馬].map { |name| Chapter.new(name:) }
    yakou.save!

    yakou.thoughts.new(comment: 'あれから十年。')
    onomichi = Chapter.find_by!(name: '尾道')
    onomichi.thoughts.new(comment: '夜が更けるなか...')
    yakou.save!
    onomichi.save!

    yakou.reload
    onomichi.reload

    assert_equal yakou.thoughts.count, 1
    assert_equal onomichi.thoughts.count, 1
    assert_equal Thought.count, 2

    yakou_thought = yakou.thoughts.first!
    assert_equal yakou_thought.thoughtable_type, 'Book'
    assert_equal yakou_thought.comment, 'あれから十年。'

    onomichi_thought = onomichi.thoughts.first!
    assert_equal onomichi_thought.thoughtable_type, 'Chapter'
    assert_equal onomichi_thought.comment, '夜が更けるなか...'
  end
end

以上です。

Discussion