インクリメンタルサーチちょっと復習

1.データ受け渡しの準備

①ルーテイングを作る。今回は割愛。

②コントローラーで

 def index

    respond_to do |format|

      format.html

      format.json

   end

end

ちなみにhtmlやjsonの後ろに{}内で処理を書いてあげると別のページに飛んでもらったりできるが、特に何も書かなければrailsのデフォルトのviewファイルへ、という感じっぽい

③index.json.jbuilder

json.array! @users do |user|

  json.id user.id

  json.name user.name

end

としてjson形式で値を渡す

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

$(function() {
  $("#インプットフォームのid名").on("keyup", function() {
    let input = $("#インプットフォームのid名").val();
    console.log(input);
  });
});

 console.logは仮置き

keyを離すたびにフォーム部分の値を.val();が取得している

 

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

①jsファイル内

$(function() {
  $("#インプットフォームのid名").on("keyup", function() {
    let input = $("#インプットフォームのid名").val();
    $.ajax({
      type: "GET",
      url: "/users",
      data: { keyword: input },
      dataType: "json"
    })
      .done(function(users) {
        console.log("成功です");
      })
      .fail(function() {
        console.log("失敗です");
      });
  });
});

 

ajaxの形式を指定する。ここはもう少し後で追記するかも。

成功時と失敗時の処理を書く。今回は仮置き。

 

②usersコントローラー内

whereを使って曖昧検索し、@usersにログイン中のユーザー以外でキーワードの文字を含むユーザーを格納する。whereの曖昧検索については次のサイトが分かり易いが、とりあえず

モデルクラス.where("列名  LIKE  ?",   "%値%")

で0文字以上の任意の文字列を含む物を配列形式で全て取得できる。

参照元https://www.sejuku.net/blog/71189

 

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

 params[:keyword]は先にajax関数でdata{keyword: input}としたkeywordでinputはテキストフィールドの値を取得して変数に格納しておいた物。キーワードが空だったらnilを返す。

 

4JSファイル内

非同期通信の結果をもらって、htmlを作成する

 ①html組み立て用の関数を場合わけして作っておく

$(function(){

  function addUser(user){

    let html = `

       <div class="json_output_field">

          ユーザーがいた場合にテンプレートリテラル内で式展開できる${}を使い、必要な情報

       を描画する。例: ${user.name}。

       </div>

  `

 $("上で組んだhtmlをくっつける場所のid名とか").append(html);

    }

 

 function addNoUser(){

    let html = `

    <div>ユーザーが見つかりません的なhtml組み立てる</div>

    `

    $("上で組んだhtmlをくっつける場所のid名とか").append(html);

     }

});

 

②2で作ったkeyup時に発火するイベント内に通信成功時と失敗時の処理を書く

 

$("検索フィールドのid名").on("keyup", function() {
    let input = $("検索フィールドのid名").val();
    $.ajax({
      type: "GET",
      url: "/users",
      data: { keyword: input },
      dataType: "json"
    })
      .done(function(users) {
        $("検索結果表示場所のid名").empty();

        if (users.length !== 0) {
          users.forEach(function(user) {
            addUser(user);
          });
        } else if (input.length == 0) {
          return false;
        } else {
          addNoUser();
        }
      })
      .fail(function() {
        alert("通信エラーです。ユーザーが表示できません。");
      });
  });

 

.failは説明要らないと思う

.doneでは前の検索結果が残ってしまわないように検索結果を表示する箇所をまず空にするために.empty()を使う。もし曖昧検索の結果受け取った配列usersが空でなければusersの各要素をuserとして扱い、addUser関数を使って表示用のhtmlを組み立てる。入力欄が空ならfalseを返し、入力があるにも関わらず該当ユーザーがいない(usersが空)の場合はユーザーが見つかりません的なhtmlを表示する。

 

補足doneが受け取ってるusers

keyupイベントでinputしてもらい、それをkeywordとして該当するユーザーをwhereで見つけて@usersに入れて1で作ったjbuilderで@usersを配列として扱いそれぞれのカラムが何に該当するかまで記述していた。なのでこのusersはコントローラー内での@usersということでいいだろう。実際htmlを組み立てる際は${user.name},${user.id}といったjbuilder内でしっかり渡した値を使っているので。というかjsファイル内の関数の引数名はあくまでその関数内での処理名で、元の名前はあんま関係無い感じか。外と関係あるのはkeyupみたいな元々決まってる名前かajax関数内の記述くらいなんかな。

 

この辺りの流れについて後日振り返ったので、そっちの方が流れの理解にはいいかも。ただこっちで書いた物を参考に端折って書いたのでこっちのメモはこっちのメモで必要なんで残しとく。