非同期通信の実装手順

# 背景
意外とよく使う非同期通信の実装手順を記しておくことで、参考にして実装効率が上がると考えたため。

## 手順
1.Gemfileに以下を記述する。

```
gem 'jquery-rails'
```
忘れずに実行する。

```

bundle install
```

2.application.jsに、以下を記述する。
  ※

```application.js

//= require jquery    // //=require_tree.より上に記述する。
```


3.コントローラーにフォーマット毎の条件分岐を書く

```users_controller.rb

def index
  @users = User.where(['name LIKE ?', "%#{params[:keyword]}%"] ).where.not(id: current_user.id).limit(10)
  respond_to do |format|
    format.html
    format.json
  end
end

```

4.コントローラーに対応するJavaScriptファイルを作成する。
[例]users.js

5.ajaxでリクエストを送るコードを書く。

```users.js

$(function(){
  $('セレクタ名').on('submit', function(e){
    e.preventDefault();　　　　　　　　　　　// 自動でリロードする機能をオフにしている
    var formData = new FormData(this);　　// フォームで入力したデータを変数に入れている
    var url = $(this).attr("action")　　　// URLを変数に入れている
    $.ajax({
      url:url,
      type:"POST",
      data:formData,
      dataType:"json",
      processData:false,　　　　　　　　　　// FormData使用時に書くもの
      contentType:false　　　　　　　　　　 // FormData使用時に書くもの
    })

```
６.アクション名に対応するjbuilderファイルを作成し、欲しい情報を記述する。
[例]index.jbuilder

```index.jbuilder

json.array! @users do |user|   # 配列にする際はarray!メソッドを使用する
  json.id user.id
  json.name user.name
end
```

7.通信成功時と失敗時の処理を書く。

```users.js
    (中略) // ajaxの記述終了
    .done(function(data){　　　　　　　　　　　　　　　　 // ajaxのデータ
      var 変数 = buildHTML(data);
      $('追加先のセレクタ').append(変数);　　　　　　　　  // 情報を追加
      $('入力していた部分のセレクタ').val('');　　　　　   // 中身をリセット
    })
    .fail(function(){
      alert('error');
    })
```

8.HTMLに追加するための関数を定義しておく

```
  function buildHTML(comment){
    var html = `追加したいHTMLの場所`
    return html;
```

##完成形

```users.js


$(function() {
  function addUser(user) {
    let html = `
      <div class="chat-group-user clearfix">
        <p class="chat-group-user__name">${user.name}</p>
        <div class="user-search-add chat-group-user__btn chat-group-user__btn--add" data-user-id="${user.id}" data-user-name="${user.name}">追加</div>
      </div>
    `;
    $("#user-search-result").append(html);
  }

  function addNoUser() {
    let html = `
      <div class="chat-group-user clearfix">
        <p class="chat-group-user__name">ユーザーが見つかりません</p>
      </div>
    `;
    $("#user-search-result").append(html);
  }
  function addDeleteUser(name, id) {
    let html = `
    <div class="chat-group-user clearfix" id="${id}">
      <p class="chat-group-user__name">${name}</p>
      <div class="user-search-remove chat-group-user__btn chat-group-user__btn--remove js-remove-btn" data-user-id="${id}" data-user-name="${name}">削除</div>
    </div>`;
    $(".js-add-user").append(html);
  }
  function addMember(userId) {
    let html = `<input value="${userId}" name="group[user_ids][]" type="hidden" id="group_user_ids_${userId}" />`;
    $(`#${userId}`).append(html);
  }
  $("#user-search-field").on("keyup", function() {
    let input = $("#user-search-field").val();
    $.ajax({
      type: "GET",
      url: "/users",
      data: { keyword: input },
      dataType: "json"
    })
      .done(function(users) {
        console.log(users)
        $("#user-search-result").empty();
        if (users.length !== 0) {
          users.forEach(function(user) {
            addUser(user);
          });
        } else if (input.length == 0) {
          return false;
        } else {
          addNoUser();
        }
      })
      .fail(function() {
        alert("通信エラーです。ユーザーが表示できません。");
      });
  });

```