Web Backend/Ruby on Rails

레일즈로 40분 만에 유튜브 개발하기

xProgrammer 2022. 5. 14. 01:00
$("#comments").html("<%= j(render("videos/comments"))%>")
<body>
	<nav class="navbar">
    	<a href="/" class="navbar-brand">METUBE</a>
    </nav>
    <%= yield %>
</body>

https://www.youtube.com/watch?v=QY69b33ui0c&t=12s 

구현할 것
- 로그인/회원가입
- 부트스트랩/폰트어썸
- 비디오/썸네일 업로드
- 비디오 목록/보기, 작성자 수정/삭제
- 페이지네이션, 제목 검색
- 댓글 작성, 삭제

사용한 코드

% rails new metube
% cd metube
% atom .
-- 서버시작
% rails s
% rails db:create
-- gemfile변경
% bundle
% rails g devise:install
% spring stop
% rails g devise:install
% rails g devise user
% rails db:migrate
-------------------------------------
% rails g scaffold video title description:text user:references view_count:integer:index
% rails db:migrate
------------------------------------------
% rails g uploader file
% rails g uploader image
% rails g migration add_file_image_to_videos file image
% rails db:migrate
--------------------------------------------
% rails g kaminari:view bootstrap4
--------------------------------------------
% rails g model comment video:references user:references body:text
% rails g controller comments
% rails db:migrate

Gemfile

# 로그인
gem 'devise'
# 다국어처리
gem 'devise-i18n'
gem 'rails-i18n'
# 부트스트랩
gem 'bootstrap'
# 폰트어썸
gem 'font-awesome-'
# 파일업로드
gem 'carrierwave'
# 페이지네이션
gem 'kaminari'

 

application.rb

module Metube
	class Application < Rails::Application
    	config.load_defaults 6.0
        config.i18n.default_locale = :ko
	end
end

application.css > application.scss

@import "bootstrap";
@import "font-awesome";

application.html.erb

<head>
	<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
</head>
<body>
	<nav class="navbar">
    	<a href="/" class="navbar-brand">
        	<%= fa_icon "youtube-play", class: "text-danger mr-1" %>
            METUBE
        </a>
        <%= form_tag videos_path, method: :get, class: "form-inline" do%>
        	<%= text_field_tag :q, params[:q], class: "form-control mr-2" %>
            <% submit_tag "검색", class: "btn btn-danger" %>
        <% end %>
        <div>
        	<% if current_user %>
            	<%= link_to "업로드', new_video_path, class: "btn btn-danger" %>
            	<%= link_to "로그아웃', destory_user_session_path, method: :delete, class: "btn " %>
            <% else %>
            	<%= link_to "로그인', new_user_session_path, class: "btn btn%>
                <%= link_to "회원가입', new_user_registration_path, class: "btn btn%>
            <% end %>
        </div>
    </nav>
    <div class="container-fluid">
    	<div class="card">
        	<div class="card-body">
            	<%= yield %>
            </div>
        </div>
    </div>
</bod>


routes.rb

Rails.application.routes.draw do
	resources :videos
    resources :comments
    devise_for :users
    
    root "videos#index"
end

index.html.erb

<div class="row">
	<%= render @videos %>
</div>
<%= paginate @videos %>

_video.html.erb

<div class="col-3 mb-3">
	<div class="card">
		<%= image_tag video.image.url, class: "w-100" if video.image? %>
		<div class="card-body">
			<%= link_to video do %>
				<strong><%= video.title %></strong>
				<p class="small"><%= truncate video.description, length: 30 %></p>
				<p class="text-gray small"><%= time_ago_in_words video.created_at %>전, 조회수<%= video.view_count.to_i %> 회</p>
			<% end %>
		</div>
	</div>
</div>

video.rb

class Video < ApplicationRecord
	mount_uploader :file, FileUploader
    mount_uploader :image, ImageUploader
    belongs_to :user
    has_many :comments, dependent: :destory
end

_form.html.erb

<div class="form-group">
	<%= form.label :title %>
    <%= form.text_field :title, class: "form-control" %>
<div>

<div class="form-group">
	<%= form.label :description %>
    <%= form.text_field :description, class: "form-control" %>
<div>

<div class="form-group">
	<%= form.label :file %>
    <%= form.file_field :file, class: "form-control" %>
<div>

<div class="form-group">
	<%= form.label :image %>
    <%= form.file_field :image, class: "form-control" %>
<div>

<div class="actions">
	<%= form.submit "등록", class: "btn btn-danger" %>
</div>

videos_controller.rb

class VideosController < ApplicationController
	before_action :authenticate_user!, only: [:create, :new, :edit, :update, :destory]
    before_action :set_video, only: [:show, :edit, :update, :destory]
	before_action :check_owner, only: [:edit, :update, :destory]

def index
	@videos = Video.all
    @videos = @videos.where("title ilike ?", "%#{params[:q]}%") if params[:q].present?
    @videos = @vidoes.page(params[:page]).per(4)
end

def create
	@video = Video.new(video_params)
    @video.user = current_user
    
end

def show
	@video.increment!(:view_count)
end

def update
	
end

def video_params
	params.require(:video).permit(:title, :description, :file, :img)
end

def check_owner
	redirect_to root_path unless @video.user == current_user
end

show.html.erb

<%= video_tag @video.file.url, controls: true, class: "w-100" if @video.file? %>
<h4>
	<%= @video.title %>
</h4>
작성자: <%= @video.user.email %>
<%= simple_format @video.description %>

조회수: <%= @video.view_count.to_i %>
<br>
<% if current_user && @video.user == current_user %>
<%= link_to '수정', edit_video_path(@video), class: "btn btn-danger" %>
<%= link_to '삭제', @video, method: delete, data: {confirm: "정말로 삭제하시겠습니까?"}, class: "btn btn-outline-danger" %>
<% end %>
<%= link_to '목록', video_path %>
<br><br

<div id="comments">
	<%= render "videos/comments" %>
    <!-- _comments. -->
    댓글 (<%= @video.comments.count %>)
    <hr>
    <%= @video.comments.each do |comment| %>
    작성자: <%= comment.user.email %>, <%= time_ago_in_words comment.created_at %>
    <%= simple_format comment.body %>
    <% end %>
    <%= form_for Comment.new do |f| %>
        <div class="form-group">
            <%= f.hidden_field :video_id, value: @video.id %>
            <%= f.text_area :body, class: "form-control" %>
        </div>
        <%= f.submit "작성", class: "btn btn-danger" %>
    <% end %>
    
</div>

comment.rb

class Comment < ApplicationRecord
	belongs_to :video
	belongs_to :user
end

comments.controller.rb

class CommentsController < ApplicationController
	before_action :autheticate_user!
    
	def create
    	@comment = current_user.comments.create(comment_params)
        @video = @comment.video
    end
    
    def destory
    	@comment = current_user.comments.find params[:id]
        @video = @comment.video
        @comment.destory
    end
    
    private 
    
    def comment_params
    	params.require(:comment).permit(:body, :video_id)
    end
end

/views/comments/create.js.erb

$("#comments").html("<%= j(render("videos/comments"))%>")

_comments.html.erb

댓글 (<%= @video.comments.count %>)
<hr>
<%= @video.comments.each do |comment| %>
작성자: <%= comment.user.email %>, <%= time_ago_in_words comment.created_at %>
<%= simple_format comment.body %>
<p><%= link_to "삭제", comment, method :delete, remote: true, data: {confirm:"정말로 삭제하시겠습니까?"} if current_user && (current_user == comment.user)%></p>
<% end %>
<%= form_for Comment.new remote: true do |f| %>
    <div class="form-group">
        <%= f.hidden_field :video_id, value: @video.id %>
        <%= f.text_area :body, class: "form-control" %>
    </div>
    <%= f.submit "작성", class: "btn btn-danger" %>
<% end %>

user.rb

class User < ApplicationRecord

	devise :database_authenticatable, :registerable,
    		:recoverable, :rememberable, :validatable
    has_many :comments
end

/views/comments/destory.js.erb

$("#comments").html("<%= j(render("videos/comments"))%>")

사용한 URL
- localhost:3000
- localhost:3000/users/sign_up: 회원가입
- localhost:3000/videos