LoginSignup
34
34

More than 3 years have passed since last update.

【Ajax】Railsでインクリメンタルサーチの実装

Last updated at Posted at 2019-08-04

インクリメンタルサーチというやつを実装したよ。

ChatSpaceでは、作ったグループ内に集まったメンバー間でのメッセージのやり取りをするという仕様なわけだけれども。

今回追加したインクリメンタルサーチは、グループ新規作成時とグループ情報編集時に、ユーザーネームを検索するという機能のために実装したよ。

コードの解説に行く前に。

インクリメンタルサーチとは

検索したい単語をすべて入力した上で検索するのではなく、入力のたびごとに即座に候補を表示させる。 逐語検索、逐次検索とも。
(引用 : https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%AF%E3%83%AA%E3%83%A1%E3%83%B3%E3%82%BF%E3%83%AB%E3%82%B5%E3%83%BC%E3%83%81)

グーグル検索で「あ」とか打ち込むと、検索候補に「アマゾン」ってできてきたりするじゃないですか。
あれのことです。
今回はイメージしやすくていいですね。
では解説に行きます。

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

1.ルーティングなどのAPIの準備をする
今回はusers#indexを使うためのルーティングを用意します。

/config/routes.rb

Rails.application.routes.draw do
  (省略)
  resources :users  , only:[:index,:edit,:update,:show]
  (省略)
  # ただindexアクションを追加しただけです。  

2.テキストフィールドを作成する

これはファイルによりけりなので、ソースコードを省略します。 
ちなみに僕の場合の作業ファイルは下記でした。
app/views/groups/_form.html.haml
(同階層のindex.html.hamlからrenderでformを読みだしてます。)

3.テキストフィールドに入力されるたびにイベントが発火するようにする

app/assets/javascripts/user.js

    $('#user-search-field').on('keyup', function(e){
        var input = $("#user-search-field").val();

'#user-search-field'がユーザー検索フォームです。
ここに文字を打ち込むたびに処理が発火します。
2行目は、変数input対して、フォームに入力された値を代入しています。

4.イベント時に非同期通信できるようにする


    $('#user-search-field').on('keyup', function(e){
        var input = $("#user-search-field").val();

        $.ajax({
            type: 'GET',                // HTTPメソッドはGETで
            url:  '/users',             // /usersのURLに (これによりusersコントローラのindexアクションが起動)
            data: { keyword: input},    // keyword: inputを送信する
            dataType: 'json'            // サーバから値を返す際はjsonである
        })

        .done(function(users){                // usersにjson形式のuser変数が代入される。複数形なので配列型で入ってくる

            if (input.length === 0) {         // フォームの文字列長さが0であれば、インクリメンタルサーチ結果を表示しないようにする
                $('#user-search-result').empty();
              }

            else if (input.length !== 0){     // 値が等しくないもしくは型が等しくなければtrueを返す。
                $('#user-search-result').empty();
                users.forEach(function(user){ // users情報をひとつずつとりだしてuserに代入
                    appendUser(user)
                });
            }

            else {
                $('#user-search-result').empty(); // ユーザーが見つからなければ「見つからない」を返す。
                appendErrMsgToHTML("一致するユーザーが見つかりません");
            }
        })

        .fail(function() {
            alert('ユーザー検索に失敗しました');
        });
    });

ちょっと長いので詳細はコメントアウトの記述に譲りますが、流れを解説します。

(※appendUser(user)とappendErrMsgToHTML("一致するユーザーが見つかりません")はメソッドです。後述します。)

keyupにより発火。

ajaxで通信をする。その際のメソッド、リクエストの指定、データの指定、データタイプの指定をしています。

これをコントローラが受け取って、jbuilderの記述に従ってjson形式でJavaScriptに戻ってきます。
(コントローラとjbuilderの記述は冗長になるので省きます。)

done⇨通信が成功した場合は文字列の長さと型(integerかstringか)で判断します。

fail ⇨アラートを出します。

5.非同期通信の値を元に、HTMLに反映します。

$(document).on('turbolinks:load', function(){

    var search_list = $("#user-search-result");
    var member_list = $("#member-append");

    function appendUser(user){
        var 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>`;
                    search_list.append(html);
    }

    function appendErrMsgToHTML(msg){
        var html = 
                    `<div class="chat-group-user clearfix">
                        <p class="chat-group-user__name">${msg}</p>
                    </div>`;
                    search_list.append(html);
    }

4の際に記述されていた、appendUser(user)とappendErrMsgToHTML("一致するユーザーが見つかりません")のメソッドを定義しています。
()内に記載しているのは引数です。

これでインクリメンタルサーチの大まかな流れは終わりです。
とっかかりは凄くハードルが高く感じますが、一個一個解説していくとそんなに難しくないかなぁと思います。

ポイントはやっぱり$.ajax内部で指定している部分かなと思います。
自動更新機能の実装なんかもしたのですが、ここの設定によるミスで頻繁にエラーが発生しました。。。

明日は自動更新機能も書きたいと思っています。

34
34
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
34
34