概要
Ruby on Rails でオートコンプリート機能付きの検索フォームを実装してみます。
gem の紹介
今回はこちらの gem を利用します。
rails4-autocomplete という名前ですが、rails5 でも利用できます。
対応手順
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 %>
検索フォームが表示されると思いますので、何かワードを入力してオートコンプリート機能が備わっているか確認してください。
ただし、この時点ではただの検索ボックスみたいなもので 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 から取得してフロントエンド側に返す処理が必要です。
検索ワードがある程度限定された検索フォームを作成する場合は、是非導入してみてください。