rails로 동영상 사이트에 좋아 기능 구현
동영상 사이트에 좋은 기능을 구현해 보았습니다.
지금은 당연하게 되고 있는 좋은 기능이지만, 어떻게 만들어지고 있는지 궁금해 포트폴리오에 시험에 실장해 보았습니다. 1 유저가 복수의 동영상에 대해서 좋아하고, 또 1 동영상에 대해 복수의 유저가 좋아하는, 이른바 다대다의 관계이므로, 유저와 동영상의 중간 테이블로서 좋아요 테이블을 작성해 갑니다.
완성도
환경
rails : v5.2.4.1
~ 구현된 기능 ~
・동영상(일람 표시, 신규 투고, 상세, 편집, 삭제)
· 사용자(신규 등록, 로그인, 편집, 로그아웃, 상세)
· 페이지 네이션
구현 절차
※좋아 기능에 관한 부분만 코멘트 아웃으로 설명 쓰고 있습니다.
$ rails g model Like user:references video:references
$ rails db:migrate
models/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :name, presence: true, uniqueness: true
has_many :videos, dependent: :destroy
# いいねはユーザーのdestroyに依存
has_many :likes, dependent: :destroy
# ユーザーがいいねしている動画
has_many :liked_videos, through: :likes, source: :video
# いいねしているかどうかを判定
def already_liked?(video)
self.likes.exists?(video_id: video.id)
end
end
models/video.rb
class Video < ApplicationRecord
validates :name, :work, presence: true
belongs_to :user
# いいねは動画のdestroyに依存
has_many :likes, dependent: :destroy
# 動画にいいねしているユーザー
has_many :liked_users, through: :likes, source: :user
mount_uploader :work, VideoUploader
end
models/like.rb
class Like < ApplicationRecord
belongs_to :user
belongs_to :video
# 1人が1つの動画に1いいね
validates_uniqueness_of :video_id, scope: :user_id
end
$ rails g controller likes
config/routes.rb
Rails.application.routes.draw do
devise_for :users
root "videos#index"
resources :users, only: [:edit, :update, :show]
# いいねを動画にネストさせる
resources :videos do
resources :likes, only: [:create, :destroy]
end
end
controllers/likes_controller.rb
class LikesController < ApplicationController
def create
# 今ログインしているユーザーによるいいね
@like = current_user.likes.create(video_id: params[:video_id])
# 今いる画面にリダイレクト
redirect_back(fallback_location: root_path)
end
def destroy
# 今ログインしているユーザーがいいねしている動画を探す
@like = Like.find_by(video_id: params[:video_id], user_id: current_user.id)
# いいねを取り消す
@like.destroy
# 今いる画面にリダイレクト
redirect_back(fallback_location: root_path)
end
end
controllers/videos_controller.rb
class VideosController < ApplicationController
def index
@videos = Video.includes(:user).page(params[:page]).order("created_at DESC").per(12)
end
def new
@video = Video.new
end
def create
Video.create(video_params)
redirect_to root_path
end
def show
@video = Video.find(params[:id])
# いいねする
@like = Like.new
end
def edit
@video = Video.find(params[:id])
end
def update
video = Video.find(params[:id])
video.update(video_params)
end
def destroy
video = Video.find(params[:id])
video.destroy
redirect_to root_path
end
private
def video_params
params.require(:video).permit(:name, :work).merge(user_id: current_user.id)
end
end
end
로그인하지 않은 사용자도 좋아요 수를 볼 수 있도록하려면 분기 필요
show.html.haml
-# ログインしている場合
- if user_signed_in?
-# かつ既にいいねしている場合
- if current_user.already_liked?(@video)
= link_to video_like_path(@video), method: :delete do
= icon('fa', 'heart', class: 'content__show__box__top__icons__heart__already')
-# かつまだいいねしていない場合
- else
= link_to video_likes_path(@video), method: :post do
= icon('far', 'heart', class: 'content__show__box__top__icons__heart__yet')
-# ログインしていない場合
- else
= icon('far', 'heart', class: 'content__show__box__top__icons__heart__yet')
= @video.likes.count
video의 index 컨트롤러에서는 video의 id 컬럼을 취득할 수 없고, 에러로 nil이 돌려주어져 버린다.
그 때문에 일람 화면에서는 표시만으로 해, 좋아 버튼은 동작하지 않게 설정.
index.html.haml
-# ログインしている場合、かつ既にいいねしている場合
- if user_signed_in? && current_user.already_liked?(video)
= icon('fa', 'heart', class: 'content__box__top__icons__heart__already')
-# それ意外の場合
- else
= icon('far', 'heart', class: 'content__box__top__icons__heart__yet')
= video.likes.count
도전
참고
Reference
이 문제에 관하여(rails로 동영상 사이트에 좋아 기능 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/naoki00m/items/9d90e919a02b34f6132d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)