LoginSignup
16
13

More than 3 years have passed since last update.

【Rails】Ajaxを用いた非同期いいね機能の実装

Last updated at Posted at 2020-04-04

目標

ezgif.com-video-to-gif.gif

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

下記実装済み。

Slim導入
Bootstrap3導入
Font Awesome導入
ログイン機能実装
投稿機能実装

いいね機能の実装

1.モデル

ターミナル
$ rails g model Like user_id:integer book_id:integer
ターミナル
$ rails db:migrate
schema.rb
ActiveRecord::Schema.define(version: 2020_04_05_115005) do
  create_table "likes", force: :cascade do |t|
    t.integer "user_id"
    t.integer "book_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end 
end
user.rb
class User < ApplicationRecord
  has_many :likes, dependent: :destroy
end
book.rb
class Book < ApplicationRecord
  has_many :likes, dependent: :destroy

  # 既にいいねしていれば「true」を返す
  def liked_by?(user)
    likes.where(user_id: user.id).exists?
  end
end
like.rb
class Like < ApplicationRecord
  belongs_to :user
  belongs_to :book
end

2.コントローラー

ターミナル
$ rails g controller likes
likes.controll.rb
class LikesController < ApplicationControllerdef 
  def create
    @book = Book.find(params[:book_id])
    #いいねボタンを連打しても1回しかいいね出来ない様に条件付与
    unless @book.liked_by?(current_user)
      like = current_user.likes.new(book_id: @book.id)
      like.save
      redirect_to @book
    end
  end

  def destroy
    @book = Book.find(params[:book_id])
    like = current_user.likes.find_by(book_id: @book.id)
    like.destroy
    redirect_to @book
  end
end

3.ルーティング

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

ビュー

3.いいねボタンをパーシャル化

books/show.html.slim
tbody
  - @books.each do |book|
    tr
      td
        = link_to book.user  do
          = book.user.name
      td
        = link_to book.title, book_path(book)
      td
        = book.body
      td
        = render 'like-button', book: book
      td
        -if book.user == current_user
          = link_to '削除', book, method: :delete, data: { confirm: '本当に削除してもよろしいですか?' }, remote: true, class: 'btn-sm btn-danger'

4.いいねボタンのパーシャルを作成

books/_like-button.html.slim
/ いいねしているかによって色を変える
- if book.liked_by?(current_user)
  = link_to book_likes_path(book), method: :delete do
    i.fas.fa-heart style='color: red;'
    / いいね数
    = book.likes.count

- else
  = link_to book_likes_path(book), method: :post do
    i.far.fa-heart
    = book.likes.count

非同期機能の実装

1.jQueryの導入

Gemfile
gem 'jquery-rails'
ターミナル
$ bundle
application.js
//= require rails-ujs
//= require activestorage
//= require turbolinks 
//= require jquery // turbolinksより下に記述
//= require_tree .

2.いいね時のジャンプ先を削除

likes.controller.rb
class LikesController < ApplicationController
  def create
    @book = Book.find(params[:book_id])
    unless @book.liked_by?(current_user)
      like = current_user.likes.new(book_id: @book.id)
      like.save
      redirect_to @book # 削除
    end
  end

  def destroy
    @book = Book.find(params[:book_id])
    like = current_user.likes.find_by(book_id: @book.id)
    like.destroy
    redirect_to @book # 削除
  end
end

3.いいねボタンにIDを付与

books/index.html.slim
td id='like-button_#{ book.id }'
  = render 'like-button', book: book

4.いいねボタンに「remote: true」を付与

books/_like-button.html.slim
- if book.liked_by?(current_user)
  = link_to book_likes_path(book), method: :delete, remote: true do
    i.fas.fa-heart style='color: red;'
    = book.likes.count

- else
  = link_to book_likes_path(book), method: :post, remote: true do
    i.far.fa-heart
    = book.likes.count

「remote: true」を付与する事で、JavaScriptファイルを呼び出せる様になる。

5.JavaScriptファイルの作成

likes/create.js.erb
$("#like-button_<%= @book.id %>").html("<%= j(render 'books/like-button', book: @book ) %>");
likes/destroy.js.erb
$("#like-button_<%= @book.id %>").html("<%= j(render 'books/like-button', book: @book ) %>");

$("#like-button_<%= @book.id %>")
➡︎ 「3」で付与したIDを指定

.html("<%= j(render 'books/like-button', book: @book ) %>");
➡︎ いいねボタンのパーシャルをrender

16
13
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
16
13