#はじめに
プログラミング初心者の皆さんこんにちは!(こちらの記事はプログラミング初心者を対象に書いています。)
今回はjavascriptをあまり書いたことのない初心者の方でも簡単につくれるrailsとjavascriptを使った「いいね(like)機能」を実装していこうと思います。
基本的なrailsの説明は省いています。
今回はrailsのひとつ完成したアプリケーションがあるとしてそこに「いいね機能」を付け足すという流れで進めていきます。
今回は例として、ツイッターのようなSNSアプリに他人のツイートにいいねできるような機能を追加していこうと思います。
なのでtweet、userモデルとtweetsコントローラーがある前提で話を進めていきます。
一つのツイートに対して一人のユーザーがいいねできるのは一回までで、ツイッターのように灰色のハートを押すといいね(createアクション)、既にいいねされている赤のハートを押すといいねを取り消すこと(destroyアクション)ができます。
#likesテーブルを作成しよう
ターミナルでlikesテーブルを作成しましょう。カラムはinteger型でuser_idとtweet_idを追加しておきましょう。
モデルファイルに以下を記述。
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というカラムを追加しましょう。
さらに同モデルファイルに以下の記述を追加しましょう。
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を使いながら記述しましょう。
Rails.application.routes.draw do
resources :tweets do
resources :likes, only: [:create, :destroy]
end
end
#アクションを定義しましょう
まずはlikes controllerを作成しましょう。作成したらそのファイルに以下を記述しましょう
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がいいね前の灰色のハートととしてます。
<% 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ファイルを作りましょう。
$("#like-buttons").html("<%= j(render partial: 'like', locals: { tweets: @tweets, likes: @likes, like: @like}) %>")
$("#like-buttons").html("<%= j(render partial: 'like', locals: { tweets: @tweets, likes: @likes }) %>");
以上です。なんとjsを書くのはたったこれだけなんですね。なので今回のいいね機能はrailsの基本を押さえている方なら、多分すぐ出来てしまいます。簡単かつ普通に動くので他にもやり方は色々ありますが、このやり方は特におすすめです。