Railsで開発していると、polymorphic(ポリモーフィック)関連という言葉を目にすることがあります。
ただ、実際に使ったことがなかったり、なんとなくで理解しているという方も多いのではないでしょうか?
この記事では、そんな方向けに ポリモーフィック関連の仕組みと使い方 を説明します。
ポリモーフィック(polymorphic)とは?
簡単に言うと、1つのモデル(テーブル)が、複数の親モデルと関連付けられる仕組みです。
例)コメント機能
Post
(投稿)親モデルPhoto
(写真)親モデルComment
(コメント)子モデル
投稿と写真にコメントをつけたい!
でも、commentsテーブルを2つ作るのは非効率。
そんなときに使えるのが polymorphic: true
です。
実装例
ER図(簡易版)
子テーブルには、関連先のモデル名を示す commentable_type
と、関連先レコードのidを示す commentable_id
という2つのカラムを用意します。
+---------+ +----------+
| posts | | photos |
+---------+ +----------+
| id |◀─┐ | id |◀─┐
| title | │ | url | │
+---------+ │ +----------+ │
│ │
▼ ▼
+-----------------------------+
| comments |
+-----------------------------+
| id |
| body |
| commentable_type (string) | ← "Post" or "Photo"
| commentable_id (integer) | ← 対象モデルのid
+-----------------------------+
モデル設定
親モデルでは:as
オプション付きのhas_many
を、子モデルでは:polymorphic
オプション付きのbelongs_to
を書きます。
ここでのポイントは、has_many
の :as
オプションや belongs_to
の引数、そして comments
テーブル内の commentable_type
/ commentable_id
というカラム名の「commentable」の部分をすべて一致させていることです。
class Post < ApplicationRecord
has_many :comments, as: :commentable
end
class Photo < ApplicationRecord
has_many :comments, as: :commentable
end
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
end
使い方
post = Post.create(title: "初投稿")
photo = Photo.create(url: "baby.png")
post.comments.create(body: "いいね!")
photo.comments.create(body: "かわいい!")
Comment.all
で確認すると、以下のようにどちらのコメントも同じ comments
テーブルに保存されます。
id | body | commentable_type | commentable_id |
---|---|---|---|
1 | “いいね!” | “Post” | 1 |
2 | “かわいい!” | “Photo” | 1 |
最後に
ポリモーフィック関連は、少しとっつきにくい名前ですが、使い方はシンプルですね。
コメント