####はじめに
今回はインクリメンタルサーチについて書いていきたいと思います。
Rails 無限スクロール(gem、ライブラリ無し)の際に作成したサンプルアプリケーションに機能を追加していきます。(前提条件(無限スクロール実装前)の時点から作業開始)
####インクリメンタルサーチとは
アプリケーションにおける検索方法のひとつ。検索したい単語をすべて入力した上で検索するのではなく、入力のたびごとに即座に候補を表示させる。逐語検索、逐次検索とも。
引用
Wikipedia
####インクリメンタルサーチ機能の作成
まずは普通の検索機能を作成し、その後インクリメンタルサーチ機能に変更していきたいと思います。
#####処理の流れ
- #indexにてbooks一覧を表示
- 検索機能の実装
- 検索窓にキー操作を行うとイベント発火
- #indexに検索キーワードを送信しレコードを取得
- jbuilderにてjson形式に変換しデータを返却する
- 返ってきたデータを元にjs側で処理
4.以降はjbuilderを利用しない方法でも実装可能です。こちらの記事に記載しています。
#####実装
######1.#indexにてbooks一覧を表示
index.html.erbを一部partial化します。
<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>
<% books.each do |book| %>
<tr>
<td class='scroll__td'><%= book.title %></td>
<td class='scroll__td'><%= book.body %></td>
</tr>
<% end %>
######2.検索機能の実装
1.検索窓の作成
<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.検索機能の作成
# 検索結果を返す
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の両方で検索できるようにしています。
class BooksController < ApplicationController
def index
key_word = params[:key_word]
@books = Book.search(key_word)
@book = Book.new
end
end
$('.scroll__tbody').html('<%= j(render 'index', books: @books) %>');
#indexには同期通信と非同期通信のどちらのリクエストも届きますので、index.html.erbとindex.js.erbを作成しています。わかりにくい場合はアクションを分けていただくと、分かりやすくなると思います。
以上で検索機能の作成は終了です。
######3.検索窓にキー操作を行うとイベント発火
ここからはインクリメンタルサーチを実装していきたいと思います。
検索窓にてinputイベントを検出したタイミングで処理を行います。
$(document).on('turbolinks:load', function() {
$(document).on('input', '.search__word', function(){
// 処理を記述
});
});
######4.#indexに検索キーワードを送信しレコードを取得
処理の中身を書いていきます。
$(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形式に変換しデータを返却する
json.array! @books do |book|
json.title book.title
json.body book.body
end
jbuilderでの変換例はこちらにいくつか載っていますが、検索すると記事もたくさん出てきますので、そちらの方がわかりやすいと思います。
######6.返ってきたデータを元に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はこちら
$(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);
});
})
});
});
以上でインクリメンタルサーチの機能実装は終了です。