✨
【Rails】ポリモーフィック関連を使って複数のテーブルに対してのいいねを実装
概要
複数のテーブルに対してのいいねを実現するには、いくつかの方法がある(都度テーブルを増やす、STI、ポリモーフィック関連)が、本記事ではポリモーフィック関連を使うやり方について紹介する。
ポリモーフィック関連とは
Railsガイドにもあるように、本来モデルは1つのモデルにしか属することができないところを、複数のモデルに属することを可能にするものである。
ポリモーフィック関連付けを使うと、ある1つのモデルが他の複数のモデルに属していることを、1つの関連付けだけで表現できる。
要件
YouTubeのような動画プラットフォームの実装を想定。ユーザーは動画、コメントにいいねできる。いいねの対象は今後増える可能性がある(例:新しく音声投稿もできるようになり、それに対してもいいねを可能にしたいなど…)
ユーザーが1つの動画やコメントにいいねできるのは1回まで(user_id
とvideo_id
は一意である)
何も考えずに実装
ユーザーは動画とコメントにいいねできる必要があるので、動画、コメントにそれぞれの専用いいねテーブルを生やす。
結果以下のようなテーブルが必要になる。
テーブル | 説明 |
---|---|
Video |
動画テーブル |
VideoLike |
動画専用いいねテーブル |
Comment |
コメントテーブル |
CommentLike |
コメント専用いいねテーブル |
User |
ユーザー |
ER図
モデル
video.rb
class Video < ApplicationRecord
has_many :video_likes
end
video_like.rb
class VideoLike < ApplicationRecord
belongs_to :video
end
comment.rb
class Comment < ApplicationRecord
has_many :comment_likes
end
comment_like.rb
class CommentLike < ApplicationRecord
belongs_to :comment
end
生じ得るデメリット
- いいねの対象のテーブル(
Video
、Comment
、Voice
)が増えるたびに、専用のいいねテーブル(VideoLike
、CommentLike
、VoiceLike
)も追加する必要があり追加コストが高い - 専用のいいねテーブルはいいねの対象が違うだけで性質はほとんど同じだが異なるテーブルとして存在するため、メンテナンス性が低下する
- 例えばいいねの仕様が変わった時に全ての専用いいねテーブルに変更が発生
ポリモーフィック関連を用いた実装
VideoLike
、CommentLike
を1つのLikeテーブルにまとめて、Video
とComment
の両方に属することが可能な設計に変更する。
結果以下のようなテーブルが必要になる。
テーブル名 | 説明 |
---|---|
Video |
動画テーブル |
Comment |
コメントテーブル |
Like |
いいねテーブル(VideoとCommentに属することが可能) |
User |
ユーザー |
ER図
モデル
like.rb
class Like < ApplicationRecord
belongs_to :likable, polymorphic: true
end
video.rb
class Video < ApplicationRecord
has_many :like, as: :likable
end
comment.rb
class Comment < ApplicationRecord
has_many :like, as: :likable
end
解決する課題
- いいねの対象のテーブルが増えたとしても、モデルに
has_many :likes, as: :likable
を追加するだけでよくなった - いいねの対象のテーブルごとにあった専用のいいねテーブルを1つのテーブルにまとめることができたため、メンテナンス性が向上
まとめ
複数のテーブルにいいねはポリモーフィック関連を使うことで、「いいねの対象の追加が容易になる」「メンテナンス性が向上する」のようなメリットがある。
参考
以下の資料が本記事を書くきっかけになりました。また内容もとても参考になりました。
ありがとうございます。
Discussion