LoginSignup
4
2

More than 3 years have passed since last update.

いいね機能の実装について

Posted at

はじめに

今回は、オリジナルアプリに実装した「いいね機能」について
振り返りながら記事を書きたいと思います。

オリジナルアプリでいいね機能は2箇所実装しました。
1.投稿に対するいいね
2.コメントに対するいいね
この2つです。
別テーブルで作成しました。

今回は、コメントに対するいいね機能の記事を書きたいと思います。
なお、ユーザー管理機能、投稿機能、コメント機能は実装済みです。

1.テーブル設計
2.モデル作成(テーブル作成、バリデーション、アソシエーション)
3.ルーティング設定
4.コントローラー設定
5.ビューの設定

バージョン

・Ruby 2.6.5
・Rails 6.0.0

テーブル設計

・likesテーブル

Column Type Options
user references null: false, foreign_key: true
post references null: false, foreign_key: true
comment references null: false, foreign_key: true

Association

  • belongs_to :user
  • belongs_to :post
  • belongs_to :comment

user、post、commentは紐づいているので、references型でオプションでforeign_key: true
をつけています。
commentにいいねしたい場合、投稿も紐づいているためpostカラムも必要になります。
どのユーザーがどの投稿のどのコメントにいいねをしたのかわかるようにしてます。
アソシエーションはユーザー、投稿、コメントは1に対してlikeは多の関係になります。

モデルの作成

テーブル設計ができましたら、次にモデルを作成します。

% rails g model like

モデルを作成したら、マイグレーションファイルに記述します。

2021xxxxxxx_create_likes.rb

class CreateLikes < ActiveRecord::Migration[6.0]
  def change
    create_table :likes do |t|
      t.references :user,    null: false, foreign_key: true
      t.references :post,    null: false, foreign_key: true
      t.references :comment,    null: false, foreign_key: true
      t.timestamps
    end
  end
end

先ほどのテーブルのカラムを記述したら、

% rails db:migrate

マイグレーションを行いテーブルを作成完了です!!

次にモデルにアソシエーションとバリデーションの記述を行います。

models/like.rb

class Like < ApplicationRecord
  belongs_to :user
  belongs_to :post
  belongs_to :comment

  validates_uniqueness_of :comment_id, scope: :user_id
end

ここでのバリデーションは、1つのコメントに対して1度しかいいねできないように
組んでいます。

ここにコードは載せませんが、User、Post、Commentのモデルに
has_many:likesの記述を行っています。

ルーティングの設定

routes.rb

Rails.application.routes.draw do
  devise_for :users

  root to: 'posts#index'
  resources :users, only: [:show, :edit, :update, :destroy]
  resources :posts do
    resources :comments, only: :create do
      resources :likes, only: [:create, :destroy]
    end
  end
end

ここで、ルーティングをネストさせます。
まず、postsコントローラー(親)→commentsコントローラー(子)の関係性があります。
そこに、commentsコントローラー(親)→likesコントローラー(子)の関係性でネストさせます。
ネストをさせる理由は、アソシエーション先のレコードのidをparamsに追加してコントローラーに送るためです。
今回だと、いいねに結びつくコメント投稿のidをparamsに追加します。

これで、ターミナルでルーティングを確認する。

% rails routes

Image from Gyazo

コントローラーの設定

まずは、コントローラーを作成します。

% rails g controller likes

次にコントローラーにコードを記述します。

controllers/likes_controller.rb

class LikesController < ApplicationController

  def create
    post = Post.find(params[:post_id])
    comment = Comment.find(params[:comment_id])
    @like = Like.create(user_id: current_user.id, post_id: post.id, comment_id: comment.id)
    redirect_to post_path(comment.post)
  end

  def destroy
    post = Post.find(params[:post_id])
    comment = Comment.find(params[:comment_id])
    Like.find_by(user_id: current_user.id, post_id: post.id, comment_id: comment.id).destroy
    redirect_to post_path(comment.post)
  end
end

ここでは、いいねの保存と削除のアクションを記述しています。

createアクション

post = Post.find(params[:post_id])
comment = Comment.find(params[:comment_id])

いいねされたコメントに紐づく投稿を変数postに格納する。
いいねされたコメントのidとPostテーブルのidが一致するものをfindで見つけて変数postに格納。

@like = Like.create(user_id: current_user.id, post_id: post.id, comment_id: comment.id)

こちらでいいねを保存する処理を記述します。

destroyアクション

def destroy
    post = Post.find(params[:post_id])
    comment = Comment.find(params[:comment_id])
    Like.find_by(user_id: current_user.id, post_id: post.id, comment_id: comment.id).destroy
    redirect_to post_path(comment.post)
  end

find_byメソッドを使用して、それぞれのidが一致したいいねを取り消す処理を記述します。

viewの記述

最後にviewの記述を行います。

views/likes/_like.html.erb

 <%if user_signed_in? %>
    <% if Like.find_by(user_id: current_user.id, post_id: @post.id, comment_id: comment.id) %>
        <%= link_to  post_comment_like_path(@post, comment, comment.likes), {class: "like-link", method: :delete } do %>
          <i class="fas fa-grin-squint-tears unlike-btn"></i>
        <% end %>
        <p class="count"><%= comment.likes.count %></p>
    <% else %>
        <%= link_to post_comment_likes_path(@post, comment), {class: "like-link", method: :post } do %>
          <i class="far fa-grin-squint-tears like-btn"></i>
        <% end %>
        <p class="count"><%= comment.likes.count %></p>
    <% end %>
  <% else %>
      <i class="fas fa-grin-squint-tears unlike-btn"></i><p class="count"><%= comment.likes.count %></p>
  <% end %>

user_signed_in?メソッドを使用しログインしていないユーザーには、カウント数だけ表示
されるようにしています。
そして、if文でfind_byメソッドを使用し、idが一致したものがあれば、削除のボタンを表示し、
一致しない時は、いいねボタンが表示されるようにしています。

以上がいいね機能実装の手順になります。
初心者の私にはかなり難しく感じました。
実装できたものの、理解できていない部分もあります。

もし何か間違いや聞きたいことがありましたら、コメント
していただければ幸いです。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2