YASD-TECH
YASD TECH
# Ruby on Rails

【Rails】複数モデルに対するいいね機能を効率化しよう!

投稿日:2024/5/21

更新日:2024/11/4

ttitleImage

【Rails】複数モデルに対するいいね機能を効率化しよう!

お疲れ様です!

今回は Rails ガイドにも記載されているポリモーフィック関連を利用したいいね機能の作成方法についての記事になります。

ポリモーフィック関連を利用することで、複数のモデルに対して共通の「いいね」機能を簡単に実装することができます。

本来どのようにいいね機能を作るか

本来いいね機能を作成しようとすると、各モデル(例えば、Post や Comment)に対して個別に「いいね」テーブルを作成する必要があります。例えば、以下のような設計になります。

例: Post モデルに対するいいね機能

  1. Post モデル
models/post.rb
   class Post < ApplicationRecord
     has_many :likes
   end
  1. Like モデル
models/like.rb
   class Like < ApplicationRecord
     belongs_to :post
     belongs_to :user
   end
  1. マイグレーションファイル
migration.rb
   class CreateLikes < ActiveRecord::Migration[6.1]
     def change
       create_table :likes do |t|
         t.references :post, null: false, foreign_key: true
         t.references :user, null: false, foreign_key: true
         t.timestamps
       end
     end
   end

いいねを行う対象モデルが 1 つの場合であればこの設計が適切ですが、複数モデルに対していいね機能を実装する場合各モデルに対して個別に「いいね」機能を実装する必要があり、モデルが増えるたびに同じようなテーブルと関連を追加する必要が出てきます。

例えば Post、Comment、Photoモデルに対していいねできるようにしたい場合、PostLike、CommentLike、PhotoLikeと三つ似たような役割のモデルを作成する必要があります。

このような場合にポリモーフィック関連を利用することで、共通の「いいね」テーブルを作成し、どのモデルに対しても簡単に「いいね」機能を追加できます。

ポリモーフィック関連を利用したいいね機能

  1. Like モデル
models/like.rb
   class Like < ApplicationRecord
     belongs_to :likeable, polymorphic: true
     belongs_to :user

     validates :user_id, uniqueness: { scope: [:likeable_type, :likeable_id], message: "has already liked this item" }
     ## 一意性を持たせるバリデーションを付与した
   end
  1. Post モデル
models/post.rb
   class Post < ApplicationRecord
     has_many :likes, as: :likeable
   end
  1. Comment モデル
models/comment.rb
   class Comment < ApplicationRecord
     has_many :likes, as: :likeable
   end
  1. マイグレーションファイル
migration.rb
   class CreateLikes < ActiveRecord::Migration[6.1]
     def change
       create_table :likes do |t|
         t.references :user, null: false, foreign_key: true
         t.references :likeable, polymorphic: true, null: false
         t.string :likable_type
         t.timestamps
       end
     end
   end

この設計の場合、LikableType にはいいねをしたモデル名が String 型で入ります。Post モデルにいいねしたのであれば"Post"、Comment モデルに対していいねしたのであれば"Comment"といった感じです!

likeable にはいいねしたモデルの中のどのレコードに対してかを入れます。Post モデルの id が 100 のものにいいねをつけたとすると

json
{

    likable: 100,

    likable_tyoe: Post

}

のようになります。

こうすることでモデルがいいね機能を追加したいモデルが複数あったとしても、いいねのモデルは作成しなくても済みます。

どのようなシーンで利用できるか

ポリモーフィック関連を利用したいいね機能は、以下のようなシーンで特に有効です。

  1. 複数のモデルに対して共通の機能を実装する場合
    • 例えば、投稿(Post)やコメント(Comment)、写真(Photo)など、複数のモデルに対して「いいね」や「コメント」などの共通機能を実装する場合に、ポリモーフィック関連を利用することでコードの重複を避けることができます。
  2. 拡張性を考慮した設計が必要な場合
    • 今後新しいモデルが追加される場合にも、ポリモーフィック関連を利用していると簡単に既存の「いいね」機能をそのまま利用できるため、拡張性が高くなります。
  3. コードの保守性を高めたい場合
    • 共通の機能を一箇所に集約することで、コードの保守性が高まり、バグの修正や機能の追加が容易になります。

まとめ

今回はちょっと発展的なDB設計についてまとめました。

ただし、この設計を行うことによるデメリットもあるので、それについてもまた今度まとめたいなぁと思います。

Index

  • 【Rails】複数モデルに対するいいね機能を効率化しよう!
  • 本来どのようにいいね機能を作るか
  • 例: Post モデルに対するいいね機能
  • ポリモーフィック関連を利用したいいね機能
  • どのようなシーンで利用できるか
  • まとめ