【Rails6】비동기(Ajax)로 팔로우 기능을 구현한다

전제


  • devise에서 사용자와 관련된 기능이 생성되었습니다
  • jquery를 사용할 수있는 환경을 구축했습니다.

    개요



    팔로우 기능의 구조에 대해서는, RailsTutorial에 상세하게 쓰여져 있으므로, 참조하는 것을 추천합니다. 이번에 사용하는 컬럼명이나 모델명은 다음과 같습니다. 메모 정도입니다만 참고 정도에 올려 둡니다.



    Relationship 모델 만들기



    콘솔에서 relationship 모델 만들기
    rails g model relationships
    
  • 참조
  • 팔로워 : user 테이블 참조
  • 팔로우 : followという名前で user 테이블을 참조한다

  • index
  • user_id와 follow_id가 일치하지 않도록 복합 키 인덱스 추가
  • 이것은 "자신이 자신을 따르는 것"을 방지합니다


  • 20210104064312_create_relationships.rb
    class CreateRelationships < ActiveRecord::Migration[6.0]
      def change
        create_table :relationships do |t|
          t.references :user, foreign_key: true
          t.references :follow, foreign_key: { to_table: :users }
    
          t.timestamps
    
          t.index [:user_id, :follow_id], unique: true
        end
      end
    end
    

    마이그레이션 실행
    rails db:migrate
    

    relationship 모델과 user 모델의 관계는 다음과 같이 기술한다.
    또한 validation도 기술.

    relationship.rb
    
    class Relationship < ApplicationRecord
      belongs_to :user
      belongs_to :follow, class_name: 'User'
    
      validates :user_id, presence: true
      validates :follow_id, presence: true
    end
    
  • 연관에 대해서는, 상기 화상을 참조해 주시면 감사하겠습니다.
  • 「팔로우한다」 「팔로우를 제외한다」 「팔로우하고 있는지 확인」의 메소드는 몇번이나 사용하므로, 정의해 둡니다.

  • relationship.rb
    class User < ApplicationRecord
      has_many :relationships, dependent: :destroy
      has_many :followings, through: :relationships, source: :follow
      has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id', dependent: :destroy
      has_many :followers, through: :reverse_of_relationships, source: :user
    
      def follow(other_user_id)
        relationships.find_or_create_by(follow_id: other_user_id) unless id == other_user_id.to_i
      end
    
      def unfollow(other_user_id)
        relationship = relationships.find_by(follow_id: other_user_id)
        relationship.destroy if relationship
      end
    
      def following?(other_user)
        followings.include?(other_user)
      end
    end
    

    view controller 만들기


  • 사용자 페이지의 경우 편집 버튼, 다른 사용자 페이지의 경우 팔로우 버튼을 표시합니다.

  • app/views/users/show.html.erb
    
    <div>
      <% if @user.id == current_user.id %>
        <%= link_to 'Edit', edit_user_registration_path(current_user) %>
      <% else %>
        <%= render partial: 'follow' %>
        <%= render partial: 'follow_count'%>
      <% end %>
    </div>
    

    app/views/users/_follow.html.erb
    
    <span id="follow">
      <%= follow_button(@user) %>
    </span>
    
  • follow_button을 정의하고 있습니다.
  • Bootstrap을 사용하는 사람은 팔로우 중인지 여부에 따라 키에 primary 또는 secondary가 들어가므로 버튼의 색상을 변경할 수 있습니다. (Bootstrap 사용하지 않는 분은 지워 버려서 문제 없습니다.)
  • remote: true 를 넣어 Ajax 통신을 할 수 있습니다.

  • app/helpers/application_helper.html.erb
    module ApplicationHelper
      def follow_button(user)
        label, key = current_user.following?(user) ? %w[フォロー中 secondary] : %w[フォローする primary]
        link_to(label, user_follow_path(@user), method: :post, remote: true, class: "btn btn-#{key} rounded-pill")
      end
    end
    
  • javascript로 작성되었습니다.
  • html内のidがfollowの中身をrenderする 수 있습니다.

  • app/views/users/follow.js.erb
    $('#follow').html('<%= j(render partial: "follow") %>');
    
  • 잊지 말고 route도 바꾸자.
  • post 통신을 하기 위해서 지정이 필요합니다.

  • routes.rb
    Rails.application.routes.draw do
      resources :users, only: %w[index show] do
        post :follow
      end
    end
    

    마지막으로


    @user.followers.count 또는 @user.followings.count 에서 팔로워 수와 팔로우 수를 계산하여 표시할 수 있습니다. 이 기사를 이해할 수 있다면 쉽게 Ajax로 구현할 수 있으므로 시도해보십시오.

    좋은 웹페이지 즐겨찾기