じぶんメモ

プログラミングのメモ、日常のメモとか。

railsでポリモーフィック関連でインターフェースっぽく振る舞わせる

railsにもインターフェースはないのかな?と思い調べてみると、
ポリモーフィック関連というものを使うそうです。
例として、Article、Eventという二つのモデルを用意し、
その両方ともにCommentモデルをhas_manyの関係で保持させたいとします。

テーブル定義

  • articlesテーブル
idID
titleタイトル
body本文
created_at作成日時
updated_at更新日時


  • eventsテーブル
idID
titleタイトル
body内容
created_at作成日時
updated_at更新日時


  • commentsテーブル
idID
commentable_id関連元レコードID
commentable_type関連元レコード種別
name発言者名
body内容
created_at作成日時
updated_at更新日時

commentable_id は、どのレコードに対するコメントなのか、
commentable_type は、commentable_idに対してどのテーブルへの関連なのかを示します。

モデル定義

class Article < ApplicationRecord
  has_many :comments, as: :commentable
end
class Event < ApplicationRecord
  has_many :comments, as: :commentable
end
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true, inverse_of: :comments
end

has_manyに as: :commentable とすることで、ポリモーフィック関連でのアソシエーションを生成します。
commentモデル側では belongs_to :commentable, polymorphic: true とすることで、
article、eventのどちらのモデルからも参照される・することを定義しています。

インターフェース部分を別ファイルに切り出すと、以下のような感じ

class Article < ApplicationRecord
  include Commentable
end
class Event < ApplicationRecord
  include Commentable
end
module Commentable
  extend ActiveSupport::Concern

  included do
    has_many :comments, as: :commentable
  end
end
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true, inverse_of: :comments
end