LoginSignup
2
0

More than 3 years have passed since last update.

Railsでフォロー機能の実装[非同期通信]

Last updated at Posted at 2021-04-08

環境

  • Bootstrap
  • jQery

追加していること

モデル

ターミナル
$ rails g model relationship

relationshipモデルの作成します。

マイグレーションファイルの修正

マイグレーションファイル
class CreateRelationships < ActiveRecord::Migration[5.2]
  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.rbの修正

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

ユーザーモデルに追加

user.rb
  has_many :relationships
  has_many :followings, through: :relationships, source: :follow
  has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id'
  has_many :followers, through: :reverse_of_relationships, source: :user

  def follow(other_user)
    unless self == other_user
      relationships.find_or_create_by(follow_id: other_user.id)
    end
  end

  def unfollow(other_user)
    relationship = relationships.find_by(follow_id: other_user.id)
    relationship.destroy if relationship
  end

  def following?(other_user)
    followings.include?(other_user)
  end

コントローラ

ターミナル
$ rails g controller relationships
relationships.rb
class RelationshipsController < ApplicationController
  before_action :ensure_user, only: [:create, :destroy, :followings, :followers]

  def create
    following = current_user.follow(@user)
    following.save
    flash[:success] = "フォローしました"
  end

  def destroy
    following = current_user.unfollow(@user)
    following.destroy
    flash[:success] = "フォローを解除しました"
  end

  def followings
    @users = @user.followings
  end

  def followers
    @users = @user.followers
  end

  private

  def ensure_user
    @user = User.find(params[:user_id])
  end
end

View

_follow_button.html.erb
<div class='row'>
  <% unless current_user == user %>
    <% if current_user.following?(user) %>
      <%= link_to 'Unfollow', user_relationships_path(user.id), class: 'btn btn-info', method: :delete, remote: true %>
    <% else %>
      <%= link_to 'Follow', user_relationships_path(user.id), class: 'btn btn-success', method: :post, remote: true %>
    <% end %>
  <% else %>
    <%= link_to '',edit_user_path(user),class: "btn btn-outline-secondary btn-lg fas fa-user-cog" %>
  <% end %>
</div>
_follow_user.html.erb
<table class="table">
  <thead>
   <tr>
    <th>image</th>
    <th>name</th>
    <th colspan="3"></th>
   </tr>
  </thead>
  <tbody>
   <% users.each do |user| %>
    <tr>
     <td><%= attachment_image_tag user, :profile_image, format: 'jpeg', fallback: "no-image-icon.jpg", size: "120x120", class: "rounded-circle m-4" %></td>
     <td><%= user.name %></td>
     <td>フォロー数: <%= user.followings.count%></td>
     <td>フォロワー数: <%= user.followers.count%></td>
     <td><%= link_to "詳細をみる", user_path(user), class: "user_#{user.idjs}" %></td>
    </tr>
   <% end %>
  </tbody>
</table>

jQueryを使用し、非同期通信

create.js.erb
$(".follow").html("<%= j(render 'relationships/follow_button', user: @user ) %>");
$(".follow-count").html("<%= @user.followers.count %>");
destroy.js.erb
$(".follow").html("<%= j(render 'relationships/follow_button', user: @user ) %>");
$(".follow-count").html("<%= @user.followers.count %>");
followings.html.erb
<div class="container">
  <div class="row">
    <div class="col">
      <h2>フォロー中</h2>
      <% if @users.exists? %>
        <%= render 'relationships/follow_user', users: @users %>
      <% else %>
        <p>ユーザーはいません</p>
      <% end %>
    </div>
  </div>
</div>
follwers.html.erb
<div class="container">
  <div class="row">
    <div class="col">
    <h2>フォロワー</h2>
      <% if @users.exists? %>
        <%= render 'relationships/follow_user', users: @users %>
      <% else %>
        <p>ユーザーはいません</p>
      <% end %>
   </div>
  </div>
</div>

追加したいところ.html.erb
<div class="follow mt-5"><%= render 'relationships/follow_button', user: @user %></div>

<div class="col-3 text-center">フォロー中 : <%= link_to @user.followings.count, user_followings_path(@user) %></div>
<div class="col-3 text-center">フォロワー : <%= link_to @user.followers.count, user_followers_path(@user), class: "follow-count" %></div>
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0