Rails 5 on aws c9

N6. Post 수정과 삭제

컴퍼 2020. 7. 5. 16:45

이번엔 수정과 삭제를 구현해보자.

<div class="container">
    <div class="row">
        <!-- 작은 사이즈에선 12개로 꽉차고, 중간사이즈부터는 4를 차지-->
        <div class="col s12 m4">
            <div class="card">
                <div class="card-image">
                    <!-- 일단은 샘플 이미지 -->
                    <img src="http://materializecss.com/images/office.jpg"/>
                </div>
                <div class="card-content">
                    <div class="card-title">
                        <!-- 로그인했다면, 현재 유저의 이름이 뜬다 -->
                        <%= current_user.name %>
                    </div>
                    <p>
                        이메일 : <%= current_user.email %>
                    </p>
                    <p>
                        <!-- posts_count 는 컨트롤러에서 작성을 해줘야 뜬다 -->
                        올린 글 개수 : <%= @posts_count %>
                    </p>
                    <!--헬퍼를 이용해 포스트 작성하기로 이동-->
                    <%= link_to new_post_path do %>
                        <button class="btn">글 쓰기</button>
                    <% end %>
                </div>
            </div>
        </div>
        <!-- 작은 사이즈에선 12개로 꽉차고, 중간사이즈부터는 8를 차지-->
        <div class="col s12 m8">
            <!-- @posts : DB에 저장된 모든 포스트를 컨트롤러에서 역순으로 보내줌-->
            <!-- 이를 하나하나 뽑아 임시변수 post로 받음-->
            <% @posts.each do |post| %>
            <div class="card">
                <div class="card-content">
                    <!-- 해당포스트의 작성자의 이름을 출력 -->
                    <span class="card-title"><%= post.user.name %></span>
                    <span><%=post.created_at %></span>
                    <p><%= post.content %></p>
                </div>
                <div class="card-action">
                    <a href="#">좋아요</a>
                    <% if current_user.id == post.user_id %>
                        <%= link_to "수정", edit_post_path(post), class: "right" %>
                    <% end %>
                    <a href="#">댓글 달기</a>
                </div>
            </div>
            <% end %>
        </div>
    </div>
</div> 

views/posts/edit.html.erb 추가 (edit 에는 내용이 차 있어야 한다)

<div class="container">
    <div class="row">
        <div class="card col s12">
            <div class="card-content">
                <div class="card-title">
                    수정하기
                </div>
                <!-- 라우트를 확인해 업데이트 액션으로 이어지게 해야함-->
                <!-- Prefix 가 다름! posts_path 대신 post_path-->
                <!-- 해당 개시글의 번호를 params id 로 받을 수 있음-->
                <!-- 컨트롤러에 @post = Post.find_by(id: params[:id]) 추가-->
                <%= form_tag post_path(@post), method: "patch" do %>
                <input type="hidden" name="id" value="<%= @post.id %>"
                <div class="input-field">
                    <%=text_area_tag :content, @post.content, class: "materialize-textarea", placeholder: "무슨 생각을 하고 있나요?" %>
                </div>
                <div class="input-field">
                    <%= button_tag "수정하기", class: "btn" %>
                </div>
                <% end %>
            </div>
        </div>
    </div>
</div>
class PostsController < ApplicationController
  before_action :authenticate_user!

  def index
    # views/posts/index.html.erb 에서 볼 수 있음
    # @posts변수에 모든 포스트를 created_at 기준 역순으로 정렬한걸 할당
    @posts = Post.all.order('created_at desc')
    # @posts_count 변수에 현재 로그인한 유저의 포스트 수를 할당
    @posts_count = current_user.posts.length
  end

  def new
  end

  def create
    #new_post라는 임시변수를 만들고
    #Post 모델에서 새로운 객체를 생성해서
    #user_id: 는 현재 로그인한 사람의 id를 넣고
    #내용은 파리미터로 온 content를 넣어서 저장해주겠다.
    new_post = Post.new(user_id: current_user.id, content: params[:content])
    if new_post.save
      redirect_to root_path
    else
      redirect_to new_post_path
    end
  end

  def edit
    #edit.html.erb에서 @post 사용할 수 있게 함
    @post = Post.find_by(id: params[:id])
  end

  def update
    #데이터베이스에서 수정할 글을 찾으려면 params[:id] 가 필요
    #<input type="hidden" name="id" value="<%= @post.id %>" 를 edit.html.erb 에 추가
    @post = Post.find_by(id: params[:id])
    #수정권한이 없으면 돌려보냄
    redirect_to root_path if @post.user_id != current_user.id

    @post.content = params[:content]

    if @post.save
      redirect_to root_path
    else
      render :edit
    end

  end

end

 

여기까지 했을 때 내용에 줄바꿈이 적용이 안됨

views/posts/index.html.erb 수정

<div class="container">
    ...
        <div class="col s12 m8">
            ...
                    **<p class="pre-line"><%= post.content %></p>**
                ...
        </div>
    ...
</div>

assets/stylesheets/posts.scss 수정

// Place all the styles related to the Posts controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

.pre-line {
    white-space: pre-line;
}

삭제를 구현하자

<div class="container">
                    ...
                    <% if current_user.id == post.user_id %>
                        <%= link_to "삭제", post_path(post), method:"delete", class: "right" %>
                        <%= link_to "수정", edit_post_path(post), class: "right" %>
                    <% end %>
                    ...
</div>
class PostsController < ApplicationController
  before_action :authenticate_user!

  ...

  def destroy
    @post = Post.find_by(id: params[:id])
    #수정권한이 없으면 돌려보냄
    redirect_to root_path if @post.user_id != current_user.id

    @post.destroy
    redirect_to root_path
  end

end

이제 코드를 효율적으로 짜보자

글을 찾아오고 권한채크하는게

update 하고 destroy 할 때 권한채크를 각각 구현했다.

edit 페이지를 권한이 없으면 아예 안띄워주는것도 구현하고싶다.

하는 상황이 올 수 있다.

이걸 프라이빗 메소드로 따로 빼자

class PostsController < ApplicationController
  before_action :authenticate_user!
  before_action :check_ownership, only: [:edit, :update, :destroy]

  def index
    # views/posts/index.html.erb 에서 볼 수 있음
    # @posts변수에 모든 포스트를 created_at 기준 역순으로 정렬한걸 할당
    @posts = Post.all.order('created_at desc')
    # @posts_count 변수에 현재 로그인한 유저의 포스트 수를 할당
    @posts_count = current_user.posts.length
  end

  def new
  end

  def create
    #new_post라는 임시변수를 만들고
    #Post 모델에서 새로운 객체를 생성해서
    #user_id: 는 현재 로그인한 사람의 id를 넣고
    #내용은 파리미터로 온 content를 넣어서 저장해주겠다.
    new_post = Post.new(user_id: current_user.id, content: params[:content])
    if new_post.save
      redirect_to root_path
    else
      redirect_to new_post_path
    end
  end

  def edit
  end

  def update
    @post.content = params[:content]

    if @post.save
      redirect_to root_path
    else
      render :edit
    end

  end

  def destroy
    @post.destroy
    redirect_to root_path
  end

  private 

  def check_ownership
    #edit.html.erb에서 @post 사용할 수 있게 함
    #데이터베이스에서 처리할 글을 찾으려면 params[:id] 가 필요
    #<input type="hidden" name="id" value="<%= @post.id %>" 를 edit.html.erb 에 추가
    @post = Post.find_by(id: params[:id])
    #수정권한이 없으면 돌려보냄
    redirect_to root_path if @post.user_id != current_user.id
  end

end