railsでポリモーフィック関連でインターフェースっぽく振る舞わせる
railsにもインターフェースはないのかな?と思い調べてみると、
ポリモーフィック関連というものを使うそうです。
例として、Article、Eventという二つのモデルを用意し、
その両方ともにCommentモデルをhas_manyの関係で保持させたいとします。
テーブル定義
- articlesテーブル
id | ID |
---|---|
title | タイトル |
body | 本文 |
created_at | 作成日時 |
updated_at | 更新日時 |
- eventsテーブル
id | ID |
---|---|
title | タイトル |
body | 内容 |
created_at | 作成日時 |
updated_at | 更新日時 |
- commentsテーブル
id | ID |
---|---|
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