Help us understand the problem. What is going on with this article?

railsとjsを使ったお手軽「いいね♡機能」

More than 3 years have passed since last update.

はじめに

プログラミング初心者の皆さんこんにちは!(こちらの記事はプログラミング初心者を対象に書いています。)

今回はjavascriptをあまり書いたことのない初心者の方でも簡単につくれるrailsとjavascriptを使った「いいね(like)機能」を実装していこうと思います。
基本的なrailsの説明は省いています。

今回はrailsのひとつ完成したアプリケーションがあるとしてそこに「いいね機能」を付け足すという流れで進めていきます。
今回は例として、ツイッターのようなSNSアプリに他人のツイートにいいねできるような機能を追加していこうと思います。
なのでtweet、userモデルとtweetsコントローラーがある前提で話を進めていきます。
一つのツイートに対して一人のユーザーがいいねできるのは一回までで、ツイッターのように灰色のハートを押すといいね(createアクション)、既にいいねされている赤のハートを押すといいねを取り消すこと(destroyアクション)ができます。

likesテーブルを作成しよう

ターミナルでlikesテーブルを作成しましょう。カラムはinteger型でuser_idとtweet_idを追加しておきましょう。
モデルファイルに以下を記述。

models/like.rb
class Like < ActiveRecord::Base
  belongs_to :tweet, counter_cache: :likes_count
  belongs_to :user
end

counter_cahce: :likes_countはリレーションされているlikeの数の値をリレーション先のlikes_countというカラムの値に入れますよって意味です。なのでlikes_countカラムをtweetsテーブルに追加しましょう。

tweetsテーブルにlikes_countカラムを追加しよう

tweetsテーブルにinteger型のlikes_countというカラムを追加しましょう。
さらに同モデルファイルに以下の記述を追加しましょう。

tweet.rb
class Tweet < ActiveRecord::Base
  has_many :likes, dependent: :destroy
  def like_user(user_id)
   likes.find_by(user_id: user_id)
  end
end

like_userメソッドは後に取り扱いますが、端的にいうとそのユーザーが既にツイートにいいねしているかどうか確認するメソッドです。

ルーティングを記述しよう

tweetsとlikesはネスト構造をとっています。resourcesを使いながら記述しましょう。

routes.rb
Rails.application.routes.draw do
  resources :tweets do
    resources :likes, only: [:create, :destroy]
  end
end

アクションを定義しましょう

まずはlikes controllerを作成しましょう。作成したらそのファイルに以下を記述しましょう

likes_controller.rb
class LikesController < ApplicationController
  def create
    @like = Like.create(user_id: current_user.id, tweet_id: params[:tweet_id])
    @likes = Like.where(tweet_id: params[:tweet_id])
    @tweets = Tweet.all
  end

  def destroy
    like = Like.find_by(user_id: current_user.id, tweet_id: params[:tweet_id])
    like.destroy
    @likes = Like.where(tweet_id: params[:tweet_id])
    @tweets = Tweet.all
  end
end

いいね(like)を増やすcreateアクションもdestroyアクションも同じで増やすたり消したりするlikeとそのあとの合計いいね数を表示するための@likes、とその後、tweetの一覧ページを表示するための@tweetsが定義されています。(ここでは説明を簡潔にしたいので記述を最低限におさえています。)

部分テンプレートを作ろう

今回はいいねボタンを部分テンプレートを使って作ります。
ユーザーがサインインしていない状態では押しても何も反応しないハートを表示します。ユーザーがサインインしているときは先ほど定義したlike_userメソッドを使いながら、そのユーザーがツイートにいいねしているかどうか判断しながら、表示を切り分けます。
ちなみに先ほど、likesのモデルファイルでcounter_cacheの記述を書いているので、tweet.like_countとするだけでそのツイートに結びつくlike数が表示されます。
どちらのアクションのパスもremote: trueの記述をしてajaxを使いながらアクションを実行します。
icon_red_heard.svgがいいね後の赤いハート、
icon_heart.svgがいいね前の灰色のハートととしてます。

_like.html.erb
<% if user_signed_in? %>
  <% if tweet.like_user(current_user.id) %>
    <%= button_to tweet_like_path(like, tweet_id: tweet.id), method: :delete, id: "like-button", remote: true do %>
      <%= image_tag("icon_red_heart.svg") %>
      <span>
        <%= tweet.like_count %>
      </span>
    <% end %>
  <% else %>
    <%= button_to tweet_likes_path(tweet), id: "like-button", remote: true do %>
      <%= image_tag("icon_heart.svg") %>
      <span>
        <%= tweet.like_count %>
      </span>
    <% end %>
  <% end %>
<% else %>
  <% = image_tag("icon_heart.svg") %>
    <span>
      <%= tweet.like_count %>
    </span>
<% end %>

JSファイルを作ろう

いよいよjsを書く時がやって来ました。
ajaxを使ったページ遷移をせずにいいねを増やしたり消したりするjavascriptファイルを作りましょう。

views/likes/create.js.erb
$("#like-buttons").html("<%= j(render partial: 'like', locals: { tweets: @tweets, likes: @likes, like: @like}) %>")

views/likes/destroy.js.erb
$("#like-buttons").html("<%= j(render partial: 'like', locals: { tweets: @tweets, likes: @likes }) %>");

以上です。なんとjsを書くのはたったこれだけなんですね。なので今回のいいね機能はrailsの基本を押さえている方なら、多分すぐ出来てしまいます。簡単かつ普通に動くので他にもやり方は色々ありますが、このやり方は特におすすめです。

YuitoSato
ScalaとかRubyとかJSとかの人
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした