Rails에서 Ajax에서 좋아하는 기능을 구현하는 방법

Rails에서 좋아하는 기능을 구현하는 방법 에서 좋아하는 기능의 구현 방법을 소개했습니다만, 이번에는 그 좋아하는 기능을 Ajax(비동기 통신) 구현하는 방법을 소개하겠습니다.
완성계는 다음과 같은 느낌입니다.


환경


  • Ruby 2.5.7
  • Rails 5.2.4

  • 전제



  • 이 기사이 좋아하는 기능이 구현되었습니다

    index.html.erb 편집



    두 개의 link_to(method: :delete 와 method: post)에 remote: true를 추가합니다.
    remote: true를 기재하는 것으로, Ajax로의 처리를 실행할 수가 있습니다.

    index.html.erb
    <div class="container">
      <h1>記事一覧</h1>
      <table class="table">
        <% @posts.each do |post| %>
          <tr>
            <td><%= post.title %></td>
            <td>
              <% if post.liked_by?(current_user) %>
                <% like = Like.find_by(user_id: current_user.id, post_id: post.id) %>
                <%= link_to like_path(like), method: :delete, remote: true do %>
                  <span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: red;">
                  <span><%= post.likes.count %></span>
                <% end %>
              <% else %>
                <%= link_to post_likes_path(post), method: :post, remote: true do %>
                  <span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: gray;">
                  <span><%= post.likes.count %></span>
                <% end %>
              <% end %>
            </td>
          </tr>
        <% end %>
      </table>
    </div>
    

    좋아요 기능 부분을 템플릿화



    index.html.erb와 같은 디렉토리에 다음 파일을 만들고, 좋아하는 기능 부분을 복사하고 붙여넣습니다.

    _like.html.erb
    <% if post.liked_by?(current_user) %>
      <% like = Like.find_by(user_id: current_user.id, post_id: post.id) %>
      <%= link_to like_path(like), method: :delete, remote: true do %>
        <span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: red;">
        <span><%= post.likes.count %></span>
      <% end %>
    <% else %>
      <%= link_to post_likes_path(post), method: :post, remote: true do %>
        <span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: gray;">
        <span><%= post.likes.count %></span>
      <% end %>
    <% end %>
    

    부분 템플릿(_like.html.erb)을 호출하기 때문에, 좋아하는 기능의 부분이 있던 곳에 render를 기술합니다.
    또, Ajax 의 처리가 되는 부분을 식별할 수 있도록(듯이) id 를 기술합니다.

    index.html.erb
    <div class="container">
      <h1>記事一覧</h1>
      <table class="table">
        <% @posts.each do |post| %>
          <tr>
            <td><%= post.title %></td>
            <td id="like-<%= post.id %>">  <!--idで識別できるようにする-->
    
           <%= render "like", post: post %>  <!--renderで部分テンプレートを呼び出す-->
    
            </td>
          </tr>
        <% end %>
      </table>
    </div>
    

    controller 편집



    각 액션의 끝에 redirect_back을 하고 있었지만, redirect_back을 하면 재로드를 하고 있어, Ajax가 동작하지 않습니다.
    따라서 redirect_back을 삭제합니다.

    likes_controller.rb
      def create
        like = Like.new(user_id: current_user.id, post_id: params[:post_id])
        @post = like.post
        like.save
      end
    
      def destroy
        like = Like.find(params[:id])
        @post = like.post
        like.destroy
      end
    

    js 파일 만들기



    remote : true로 js 형식의 요청을 보내고 있기 때문에 실행할 액션 이름 (create 또는 destroy)의 js 파일을 궁극적으로 찾으러갑니다.
    따라서 app/views/아래에 likes 폴더를 만들고 그 안에 create.js.erb 및 destory.js.erb를 만듭니다.

    create.js.erb
    $("#like-<%= @post.id %>").html("<%= j(render 'posts/like', post: @post) %>");
    

    destory.js.erb
    $("#like-<%= @post.id %>").html("<%= j(render 'posts/like', post: @post) %>");
    

    id로 식별하고 부분적으로 html을 다시 씁니다.
    이것으로 완성입니다.
  • 좋은 웹페이지 즐겨찾기