【rails】Ajaxを使ったフォローボタンの実装で躓いたところ

#はじめに

初学者がポートフォリオ作成の際に躓いたことをメモします。
今回は躓いた部分だけ記載します。全体を知りたい方は下記のリンクがわかりやすいです。
https://railstutorial.jp/chapters/following_users?version=4.2#sec-a_working_follow_button_the_standard_way
https://qiita.com/Kaisyou/items/e918b77465e3f55c97a2

##Ajaxとは
『Ajaxとは、あるWebページを表示した状態のまま、別のページや再読込などを伴わずにWebサーバ側と通信を行い、動的に表示内容を変更する手法。ページ上でプログラムを実行できるプログラミング言語JavaScriptの拡張機能を用いる。』

簡単に言うと、『javascriptによって必要な部分だけを更新する技術。その為ページ全体を再読み込みする必要がなく、素早いレスポンスが可能になる』と言ったところでしょうか？


##前提
今回はユーザー一覧画面（users/index）でフォローボタンを表示します。

```ruby:users_controller.rb
def index
    @q = User.ransack(params[:q])
    @users = @q.result(distinct: true)
  end
```


```ruby:users/index.slim
- @users.each do |user| 
# (中略)
  == render "follow_form" , object: @user if logged_in?
```

```ruby:users/_follow_form.slim
- unless current_user?(object) 
  div id="follow_form_#{object.id}"  #フォロー一覧画面でボタンを表示させる際にuserを区別する為に動的にしている
    - if current_user.following?(object) 
      = render 'unfollow' , object: object
    - else 
      = render 'follow' , object: object
```

```ruby:users/_follow.slim
= form_with(model: current_user.active_relationships.build) do |f| 
 = hidden_field_tag :followed_id, object.id 
 = f.submit "Follow", class: "btn btn-primary" 
```

##躓いたところ(1)　relationships_controller.rb内の`respond_to`について  
他の記事を見ると`respond_to`を使っている場合が多かったが内容が理解出来なかった。
respond_toについて以下のリンクがわかりやすかった。
https://www.javadrive.jp/rails/controller/index7.html#section3  
送られてくるリクエストの形式によって処理を分ける。リクエストがHTML形式で送られてきた場合とjs形式で送られてきた場合で処理を分けている。

```ruby:relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :logged_in_user

  def create
    @user = User.find(params[:followed_id])
    current_user.follow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

end
```
<br>
しかし今回はform_withでremote:trueを設定している為、HTML形式でリクエストが送られることはないので以下のようにした。

```ruby:relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :logged_in_user

  def create
    @user = User.find(params[:followed_id])
    current_user.follow(@user)
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow(@user)
  end

end
```

remote:trueを設定している為、JS形式のリクエストが送られる。デフォルトでアクション名と同じ名前のjsファイルが呼ばれる。 
（ createアクションの場合：　app/views/relationships/create.js.erb ）

<br>
##躓いたところ(2)　create.js.erb内の`"#follow_form_<%= @user.id %>`
JQueryのコードの理解が足りずバグが発生した。users/show画面では`#follow_form`で良いが、ユーザー 一覧画面の場合ユーザー を区別しなければならない為、idを動的に変更する必要がある。

```ruby:views/relationships/create.js.erb
$("#follow_form_<%= @user.id %>").html("<%= j(render 'users/unfollow', object: @user) %>");　
$("#followers").html('<%= @user.followers.count %>');  #ユーザー一覧画面では使わない（フォロワーの数を表示しない為）
```

上記のコードはJQueryで書かれており、htmlメソッドは指定した要素を書き換えることができる。  
htmlメソッドについて　https://www.sejuku.net/blog/38267  
一行目でusers/showの`#follow_form<%= @user.id %>`の内容をusers/unfollowに置き換えている。また`@user`を`users/unfollow`内でobjectとして参照している。


##最後に
誰かのお役にたてれば幸いです。
間違えている部分があればコメントお願いいたします。