目標
開発環境
・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