Railsで非同期のフォロー・フォロワー機能をつけるには？？

>前提として、deviseのgemを使ってユーザー登録の機能やマイページを作成済みであるとしましす。マイページのアクションをusers#showとしています。
とりあえずコードを載せてる状態ですので、詳しい内容はまた後日追記させていただきます。

#目次
⒈Relationshipモデルの作成とマイグレーション
⒉RelationshipモデルとUserモデルにメソッドを記述
⒊Relationshipコントローラーの作成とアクションを記述
⒋ルーティングを作成
⒌jqueryを導入
⒍viewを作成
⒎JSの作成

全体の流れを説明すると、バックエンドではユーザー同士の関係を登録するrelationshipsテーブルとそれに伴ったRelationshipモデルを作ります。モデルで既フォローかどうか判定するメソッドなどを作ります。フロントではjqueryを用いて非同期でフォロー・アンフォローを行えるようにしています。renderのいい勉強にもなると思うので参考にしてください。

#⒈Relationshipモデルの作成とマイグレーション
まずはRelationshipモデルを作成します。○○○○○○○○○○○○○○_create_relationships.rbと言うマイグレーションファイルが作れたかと思うのでまずはそちらを編集しましょう。

```○○○○○○○○○○○○○○_create_relationships.rb
class CreateRelationships < ActiveRecord::Migration[6.1]
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :following_id
      t.index [:follower_id, :following_id], unique: true
      t.timestamps
    end
  end
end
```
上記のような形にしてください。
そしたらマイグレーションを実行しましよう。

#⒉RelationshipモデルとUserモデルにメソッドを記述
それぞれ下記のようにしてメソッドを作成します。上がRelationshipモデル、下がUserモデルです。

```Relationship.rb
class Relationship < ApplicationRecord
    #自分をフォローしているユーザー
    belongs_to :follower, class_name: "User"

    #自分がフォローしているユーザー
    belongs_to :following, class_name: "User"

    #バリデーション
    validates :follower_id, presence: true
    validates :following_id, presence: true
end
```

```User.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :tweets

  has_many :following_relationships, foreign_key: "follower_id", class_name: "Relationship",  dependent: :destroy
  has_many :following, through: :following_relationships
  has_many :follower_relationships, foreign_key: "following_id", class_name: "Relationship", dependent: :destroy
  has_many :followers, through: :follower_relationships

  def following?(user)
    following_relationships.find_by(following_id: user.id)
  end

  #フォローするときのメソッド
  def follow(user)
    following_relationships.create!(following_id: user.id)
  end

  #フォローを外すときのメソッド
  def unfollow(user)
    following_relationships.find_by(following_id: user.id).destroy
  end

end
```

1のマイグレーションファイルとモデルの内容についてはまた後日解説を追記いたします。

#⒊Relationshipコントローラーの作成とアクションを記述
Relationshipコントローラーは以下のようになります。createがフォロー、destroyがフォロー解除のアクションです。2のモデル内のメソッドの内容が深く関係しています。

```relationship_controller.rb
class RelationshipsController < ApplicationController
    def create
        @user = User.find(params[:following_id])
        current_user.follow(@user)
      end
  
      def destroy
        @user = User.find(params[:id])
        current_user.unfollow(@user)
      end

    private
end
```

#⒋ルーティングの作成
routes.rbに以下を記述します。

```routes.rb
resources :relationships, only: [:create, :destroy]
```
以上です。

#⒌jqueryを導入
非同期（ajaxと言ったりします）での実装と言うことで、jqueryを導入しています。
application.html.erbのheadタグの中、```<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>```よりも上の位置に ```<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>```
を入れてください。大体以下のような形になります。

```application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Twitter</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <%= stylesheet_link_tag 'application', meda: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
    
  </head>
以下略
```

これだけでjqueryの導入は終了です。

#⒍viewを作成
viewでは、 ```render```と言うメソッドを使って実装します。これはざっくり言ってしまうと、renderと書いた部分を、指定した他のviewファイルの内容に置き換えるメソッドです。

user#showのviewファイルをまずは編集します。

```show.html.erb
<h1>users#show</h1>
<p>メールアドレス : <%= @user.email %></p>
  <%= render "follow_form" %>
<h2>ユーザーの投稿一覧</h2>

<% @user.tweets.each do |t| %>
  <%= t.body %>
<% end %>

<%= link_to "Tweet一覧に戻る", tweets_path %>

```

上記では、``` <%= render "follow_form" %>```の位置を、_follow_form.html.erb（アンダーバーから始まるファイルをパーシャルファイルと言って、ほぼrender専用のファイルです！）と言うファイルの内容に置き換える、と言うことです。
views/users直下に、```_follow_form.html.erb```のファイルを作成しましょう。

```_follow_form.html.erb
<% if user_signed_in? && @user != current_user %>
  <div id="follow_form">
    <% if current_user.following?(@user) %>
      <%= render "unfollow" %>
    <% else %>
      <%= render "follow" %>
    <% end %>
  </div>
<% end %>
```

上記のような形になりまうす。そしてなんと、さらに再びrender
が出てきました…```_unfollow.html.erb```と```_follow.html.erb```の二つのファイルを、こちらもviews/users直下に作りましょう！

```_follow.html.erb
<div class="follower">
  <h5 style="color: black;">フォロワー<%= @user.followers.count %>人</h5>
</div>
<div class="follow">
  <h5 style="color: black;">フォロー<%= @user.following.count %>人</h5>
</div>
<div>
    <%= form_for(current_user, url: relationships_path, method: :post, remote: true) do |f| %>
        <%= hidden_field_tag :following_id, @user.id %>
        <%= f.submit "フォローする", class: "btn btn-outline-secondary" %>
    <% end %>
</div>
```

```_unfollow.html.erb
<div class="follower">
  <h5 style="color: black;">フォロワー<%= @user.followers.count %>人</h5>
</div>
<div class="follow">
  <h5 style="color: black;">フォロー<%= @user.following.count %>人</h5>
</div>
<div>
<%= form_for(current_user, url: relationship_path(@user), method: :delete, remote: true) do |f| %>
    <%= f.submit "フォロー解除", class: "btn btn-outline-secondary" %>
<% end %>
</div>
```

#⒎JSの作成
非同期でパーシャルファイルを呼び出すためのJSファイルを作成します。
views/relationshipsのフォルダーの中に、```create.js.erb```と、```destroy.js.erb```を作成しましょう。それぞれの中身を下に書いておきます。

```views/relationships/create.js.erb
$("#follow_form").html("<%= j(render("users/unfollow")) %>");
```

```views/relationships/destory.js.erb
$("#follow_form").html("<%= j(render("users/follow")) %>");
```

これで非同期で画面を変えられるようになります！詳しい説明はまた後日追記いたします！