6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails インクリメンタルサーチ

Last updated at Posted at 2021-09-04

####はじめに
今回はインクリメンタルサーチについて書いていきたいと思います。
Rails 無限スクロール(gem、ライブラリ無し)の際に作成したサンプルアプリケーションに機能を追加していきます。(前提条件(無限スクロール実装前)の時点から作業開始)

####インクリメンタルサーチとは
アプリケーションにおける検索方法のひとつ。検索したい単語をすべて入力した上で検索するのではなく、入力のたびごとに即座に候補を表示させる。逐語検索、逐次検索とも。

引用
Wikipedia

####完成イメージ
ezgif.com-gif-maker (1).gif

####インクリメンタルサーチ機能の作成
まずは普通の検索機能を作成し、その後インクリメンタルサーチ機能に変更していきたいと思います。

#####処理の流れ

  1. #indexにてbooks一覧を表示
  2. 検索機能の実装
  3. 検索窓にキー操作を行うとイベント発火
  4. #indexに検索キーワードを送信しレコードを取得
  5. jbuilderにてjson形式に変換しデータを返却する
  6. 返ってきたデータを元にjs側で処理

4.以降はjbuilderを利用しない方法でも実装可能です。こちらの記事に記載しています。

#####実装
######1.#indexにてbooks一覧を表示
index.html.erbを一部partial化します。

app/views/books/index.html.erb
<h4>新規投稿</h4>
<div class='scroll__new'>
  <%= render 'new', book: @book %>
</div>

<h4>投稿一覧</h4>
<table class='scroll__table'>
  <thead>
    <tr>
      <th class='scroll__th'>タイトル</th>
      <th class='scroll__th'>内容</th>
    </tr>
  </thead>
  <tbody class='scroll__tbody'>
    <%= render 'index', books: @books %>
  </tbody>
</table>
app/views/books/_index.html.erb
<% books.each do |book| %>
  <tr>
    <td class='scroll__td'><%= book.title %></td>
    <td class='scroll__td'><%= book.body %></td>
  </tr>
<% end %>

######2.検索機能の実装
1.検索窓の作成

app/views/books/index.html.erb
<div class='search'>
  <%= form_with url: books_path, method: :get do |f| %>
    <%= f.text_field :key_word, placeholder:'キーワード', class:'search__word' %>
    <%= f.submit '検索'%>
  <% end %>
</div>

2.検索機能の作成

app/models/book.rb
# 検索結果を返す
def self.search(key_word)
  if key_word == ''
    books = Book.all
  else
    books = Book.where(['title LIKE(?) OR body LIKE(?)', "%#{key_word}%", "%#{key_word}%"])
  end
end

titleとbodyの両方で検索できるようにしています。

app/controllers/books_controller.rb
class BooksController < ApplicationController

  def index
    key_word = params[:key_word]
    @books = Book.search(key_word)
    @book = Book.new
  end
end
app/views/books/index.js.erb
$('.scroll__tbody').html('<%= j(render 'index', books: @books) %>');

#indexには同期通信と非同期通信のどちらのリクエストも届きますので、index.html.erbとindex.js.erbを作成しています。わかりにくい場合はアクションを分けていただくと、分かりやすくなると思います。
以上で検索機能の作成は終了です。

######3.検索窓にキー操作を行うとイベント発火
ここからはインクリメンタルサーチを実装していきたいと思います。
検索窓にてinputイベントを検出したタイミングで処理を行います。

app/assets/javascripts/search.js
$(document).on('turbolinks:load', function() {
  $(document).on('input', '.search__word', function(){
    // 処理を記述
  });
});

######4.#indexに検索キーワードを送信しレコードを取得
処理の中身を書いていきます。

app/assets/javascripts/search.js
$(document).on('turbolinks:load', function() {
  $(document).on('input', '.search__word', function(){
    // tbodyの中身を一度空にする
    $('.scroll__tbody').html('');
    // 検索ワードの取得
    const key_word = $(this).val();
    // #indexにajax通信
    $.ajax({
      type: 'GET',
      url: '/books',
      data: {key_word: key_word},
      dataType: 'json'
    })
    .done(function(data){
      // 返ってきたdataに対して処理を実行
    })
  });
});

######5.jbuilderにてjson形式に変換しデータを返却する

app/views/books/index.json.jbuilder
json.array! @books do |book|
  json.title book.title
  json.body book.body
end

jbuilderでの変換例はこちらにいくつか載っていますが、検索すると記事もたくさん出てきますので、そちらの方がわかりやすいと思います。

######6.返ってきたデータを元にjs側で処理

app/assets/javascripts/search.js
// .done(function(data)の中身
// 返ってきたdataに対して処理を実行
data.forEach(function(data){
  const html = `
    <tr>
      <td class='scroll__td'>${data.title}</td>
      <td class='scroll__td'>${data.body}</td>
    </tr>
  `;
  $('.scroll__tbody').prepend(html);
});
最終的なsearch.jsのcodeはこちら
app/assets/javascripts/search.js
$(document).on('turbolinks:load', function() {
  $(document).on('input', '.search__word', function(){
    // tbodyの中身を一度空にする
    $('.scroll__tbody').html('');
    // 検索ワードの取得
    const key_word = $(this).val();
    // #indexにajax通信
    $.ajax({
      type: 'GET',
      url: '/books',
      data: {key_word: key_word},
      dataType: 'json'
    })
    .done(function(data){
      data.forEach(function(data){
        const html = `
          <tr>
            <td class='scroll__td'>${data.title}</td>
            <td class='scroll__td'>${data.body}</td>
          </tr>
        `;
        $('.scroll__tbody').prepend(html);
      });
    })
  });
});

以上でインクリメンタルサーチの機能実装は終了です。

6
3
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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?