インクリメンタルサーチの実装

##インクリメンタルサーチ?
簡単に言うと検索できるようにするってことで、目次に沿って早速始めます！
※完全に自分のアウトプット用なので不明瞭な部分があればすいません！

---

###目次
1. ルーティングなどAPI側の準備
2. イベントの設定
3. イベント時に非同期通信
4. 非同期通信の結果を得て、HTMLを作成
5. 作成したHTMLをビュー上に追加

---

###1. ルーティングなどAPI側の準備

```routes.rb
Rails.application.routes.draw do
  devise_for :users
  root 'groups#index'
  resources :users, only: [:index, :edit, :update]  ←index追加
  resources :groups, only: [:new, :create, :edit, :update] do
   resources :messages, only: [:index, :create]
  end
end
```



```users_controller.rb
def index
  respond_to do |format|
    format.html
    format.json
  end
end
```
これでサーバーはJSON形式で値を返し、jbuilderファイルが読み込まれるようになる

次にファイルを作成

```
app
　└ views
　    ├ users                 
　    │   ├ edit.html.haml   
　    │   └ index.json.jbuilder   ←作成 ※indexはアクション名 
　    │   
```

`index.json.jbuilder`の中身を以下のように記述

```ruby
json.array! @users do |user|
  json.id user.id
  json.name user.name
end
```
---

###2. イベントの設定

```users.js
$(function() {
  $('#UserSearch__field').on('keyup',function() {
    let input = $('#UserSearch__field').val();
  })
})
```
keyup →　入力するためにキーが押された後、上がるタイミングで処理が実行される
val()で$('#UserSearch__field')の情報を取得

---

###3. イベント時に非同期通信

```users.js
$(function() {
  $('#UserSearch__field').on('keyup',function() {
    let input = $('#UserSearch__field').val();
// ↓↓↓↓↓　ここから追記　↓↓↓↓↓
    $.ajax({
      url: '/users',
      data: { keyword: input }
      type: 'GET',
      dataType: 'json',
    })
    .done(function(users) {

    })
    .fail(function() {

    })
  })
```

まず、**data: { keyword: input }**のkeywordについて
これは正直なんでもよくて、hogeでもappleでも。
検索、特にkeyupに関することなのでkeywordとしました。
続いて**input**は3行目の変数inputのこと。

```users_controller.rb
def index
    return nil if params[:keyword] == ""
    @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 
```
ここのストロングパラメータのkeywordに関しては、
`users.js`でkeywordとしているのでそのまま継承
**return nil if params[:keyword] == ""**の意味は
もしkeywordが空の場合はnilをreturnしますよ〜

その下の長いのはあいまい検索のテンプレに値をはめ込んでいけばOK
`model名.where('検索するカラム名 LIKE(?)', "検索ワード")`
今回は`.where.not(不要な情報)`と`.limited(数)`をくっつけた感じ。
`不要な検索の除外`と、`検索件数の取得上限`を設定してます


---

###4. 非同期通信の結果を得て、HTMLを作成

```users.js
$(function() {
  $('#UserSearch__field').on('keyup',function() {
    let input = $('#UserSearch__field').val();
    $.ajax({
      url: '/users',
      data: { keyword: input }
      type: 'GET',
      dataType: 'json',
    })
    .done(function(users) {
// ↓↓↓↓↓　ここから追記　↓↓↓↓↓
      $("#UserSearchResult").empty();
      if (users.length !== 0) {
        users.forEach(function(user) {
          addUser(user);
        });
      } else if (input.length == 0) {
      return false;
      } else {
        addNoUser();
      }
// ↑↑↑↑↑　ここまで追記　↑↑↑↑↑
    })
    .fail(function() {

    })
  })
```
empty()は子要素を削除してるらしいけど、一体何のために？と思って調べてみました
例えばデータベースに下記の名前のユーザーが登録されているとします
tanaka
tamiya
で、検索をかけると"t"を打ち込んだ時点で"tanaka"と"tamiya"がヒットします
"ta"までは2つの検索候補が上がりますが、"tan"まで打ち込むと"tamiya"は削除されます
この動きをさせるためにempty()が必要なんですね〜細かい...

次にこの部分↓

```users.js
if (users.length !== 0) {
 users.forEach(function(user) {
   addUser(user);
```
入力された名前がデータベースに登録してある（0じゃない）とき、
検索にヒットしているユーザーを出しますよ〜
※addUserはあとで使います

そして↓

```users.js
} else if (input.length == 0) {
return false;
} else {
  addNoUser();
      }
```
何も入力していないときはfalseですよ〜
入力してるけどデータベースにはない情報なので addNoUserです〜
という感じ
※addNoUserもあとで使います

---

###5. 作成したHTMLをビュー上に追加


```users.js
$(function() {
// ↓↓↓↓↓　ここから追記　↓↓↓↓↓
  function addUser(user) {
      let html = `
                  <div class="ChatMember clearfix">
                    <p class="ChatMember__name">${user.name}</p>
                    <div class="ChatMember__add ChatMember__button" data-user-id="${user.id}" data-user-name="${user.name}">追加</div>
                  </div>
                  `;
      $('#UserSearchResult').append(html);
  }

  function addNoUser() {
    let html = `
                <div class="ChatMember clearfix">
                  <p class="ChatMember__name">ユーザーが見つかりません</p>
                </div>
                `;
      $('#UserSearchResult').append(html);
  }
// ↑↑↑↑↑　ここまで追記　↑↑↑↑↑
  $("#UserSearch__field").on("keyup", function() {
    let input = $("#UserSearch__field").val();
// 以下省略
```

`addUser`と`addNoUser`をメソッドとして使用。
それぞれの範囲内で**append**してさっきの条件分岐で描画されるようになってます。
htmlの部分は検証ツールで該当するDOMをコピーしてきたら良いかな。
※html３行目に関してはオリジナルで追記する必要あり

---

一応これでインクリメンタルサーチの実装は完了です。

が！！！！！！！！！！！

検索でヒットしたユーザーを追加したり削除したり、
最終的にそれをデータベースに保存できるようにしたりしないといけないのです...
この後もやること盛りだくさん。

でも『インクリメンタルサーチの実装』なので今回はこの辺で、、
続きはまた次回につなげていきたいと思います。

ここまで読んでいただきありがとうございます。
ご意見、アドバイス等、なんでもお待ちしております。