きゃまなかのブログ

新卒6年目の WEB エンジニアです。 Ruby on Rails の TIPS を中心にブログ書いてます。 去年まで運用・保守のエンジニアだったので、サーバサイドの記事もたまに書きます。 よろしくお願いします。

【Ruby on Rails】オートコンプリート機能付き検索フォームを実装する

概要

Ruby on Rails でオートコンプリート機能付きの検索フォームを実装してみます。

gem の紹介

今回はこちらの gem を利用します。

rails4-autocomplete という名前ですが、rails5 でも利用できます。

github.com

対応手順

1. Gemfile の修正

初めに Gemfile に rails4-autocomplete を追加します。

Gemfile に記載したら bundle install でパッケージをインストールします。

$ vim Gemfile
gem 'rails4-autocomplete' # 追記

# Gemfile に書かれた gem パッケージと、その依存パッケージをインストールします
$ bundle install --path vendor/bundle

2. application.js の修正

次に app/assets/javascripts/application.js に autocomplete-rails.js を利用する旨の記述をします。

これで rails4-autocomplete に含まれている  autocomplete-rails.js を利用できるようになります。

//= require jquery
//= require jquery_ujs
//= require autocomplete-rails # 追加
//= require turbolinks
//= require_tree .

3. Controller の修正

ここまで完了したら、オートコンプリート機能を利用したいクラスの Controller に以下のアクションを追加します。

引数には取得したい model 名と column 名をセットで記載します。

他のクラス又は全てのクラスで利用できるように application_controller.rb に書いてしまうのも良いと思います。

今回、自分はそうしてます。

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception
# 第 1 引数 => model名 :user (必須)
# 第 2 引数 => column名 :name (必須)
# 第 3 引数 => オプション full: true (任意) autocomplete :user, :name, full: true # 追加 end
full オプション

デフォルトは前方一致検索のみです。全検索(部分一致検索・後方一致検索)したい場合には設定を true にします。

例えば、ruby on rails と言うワードを検索したい場合、デフォルトでは ruby で検索した場合しかヒットしません。

このオプションを true にすると on や rails で検索した場合もヒットするようになります。

他にもオプションがあるので確認してください。

https://github.com/peterwillcn/rails4-autocomplete#options

4. ルーティングの設定

先ほど作成したアクション名を使って、ルーティングの設定を追加します。

$ vim config/routes.rb

Rails.application.routes.draw do
  resources :users do
    get :autocomplete_user_name, on: :collection # 追加
  end
end

 

これで /users/autocomplete_user_name と言うパス (URL) が作成されます。

curl コマンドを叩いて動作確認をしてみます。

すると以下のようにユーザー名一覧の配列が取得できます。

※ この時点で既に users テーブルにデータを格納しておく必要があります。

オートコンプリート機能は Ajax 処理で、検索フォームに何かワードを入れるとバックエンドでこの URL を叩いて情報を取得してフロントエンドに表示しています。

$ curl 'http://localhost/users/autocomplete_user_name'

["aaaaaaaaaa","bbbbbbbbbb","cccccccccc","dddddddddd","aaaaabbbbb","cccccddddd","aaaaaccccc","bbbbbddddd"]               

5. View の修正

最後にオートコンプリート機能付きの検索フォームを表示したい箇所に以下の View ヘルパーを設置します。

<%= autocomplete_field_tag 'user[name]', nil,  autocomplete_user_name_users_path %>

 

検索フォームが表示されると思いますので、何かワードを入力してオートコンプリート機能が備わっているか確認してください。

f:id:kyamanak83:20180527221847p:plain

ただし、この時点ではただの検索ボックスみたいなもので Controller 側に入力されたデータを渡す機能がありません。

6. form の実装

検索フォームで入力された値を Controller に渡せるようにします。

今回は users_path('/users')に入力データを渡します。

Rails は URL にアクセスする HTTPメソッドによって挙動が変わります。

'/users' に POST でデータを渡すと新規作成になってしまうので、GET で渡すようにしてください。

また Rails の form_tag はデフォルトではパラメーターに utf8=✓ が付与されます。

こちらも不要だと思ったので enforce_utf8: false で除外しました。

<%= form_tag(users_path, method: :get, enforce_utf8: false) do %>
  <%= autocomplete_field_tag 'user[name]', nil,  autocomplete_user_name_users_path %>
<% end %>

7. 検索機能の実装

検索フォームで入力されたデータを Controller で受け取ります。

params[:user][:name] に入力されたデータが入っています。

Controller の処理は以下のようにしました。

  • 検索クエリがあれば該当するユーザーを返します。
  • 検索クエリがなければ全ユーザーを返します。
# GET /users
# GET /users.json
def index
# 検索クエリ: params[:user][:name] if params[:user] && params[:user][:name] user_name = params[:user][:name] @users = User.where("name LIKE '%#{user_name}%'") else @users = User.all end end

 

オートコンプリート機能が付いていれば、検索フォームから入力されたデータは補完された上で Controller 側に渡されるので、完全一致でも良いかもしれません。

※ User.where(name: user_name) でも良いと言う事です。

まとめ

オートコンプリート機能の付きの検索フォームを実装しました。

gem を利用すればフロントエンド側は autocomplete_field_tag を記載するだけで簡単に実装する事ができます。

バックエンド側は検索クエリに一致するデータを DB から取得してフロントエンド側に返す処理が必要です。

検索ワードがある程度限定された検索フォームを作成する場合は、是非導入してみてください。