【Rails】Ajax를 이용한 비동기 좋아요 기능 구현

목표





개발 환경



· 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

좋은 웹페이지 즐겨찾기