19
20

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 5 years have passed since last update.

railsでサジェスト機能を実装してみた

Last updated at Posted at 2019-10-28

railsでサジェスト機能を実装した時のメモ🍣

autocomplete系のgemが軒並みメンテされていなかったので、jquery-uiで実装していきます。

動作環境

rails 5.2.2.1
jquery-ui-rails 6.0.1

やること

company属性を持つUserというモデルを想定し、
User作成画面でcompanyのテキストフィールドに入力した際、
既にDBに存在するデータをもとに候補をサジェストする機能を実装します😎

こういうやつ↓
サジェスト.mov.gif

Gemfile

Gemfileに下記を追加しbundle install

Gemfile
gem 'jquery-ui-rails'
bundle install

application.js

下記を追加

/assets/javascripts/application.js
//= require jquery-ui/widgets/autocomplete

application.scss

下記追加

/assets/stylesheets/application.scss
 @import "jquery-ui/autocomplete";
 @import "jquery-ui/theme";
 @import "jquery-ui/menu";

筆者環境だと、theme、menuを外すと表示が崩れました🤔

routes.rb

サジェストの配列を返すルートを追加します。

routes.rb
  resources :users do
    get '/autocomplete_company/:company', on: :collection, action: :autocomplete_company
  end

モデル

前方一致検索のscopeを追加します。

user.rb
  # 前方一致検索
  scope :by_company_like, lambda { |company|
    where('company LIKE :value', { value: "#{sanitize_sql_like(company)}%"})
  }

コントローラー

サジェストの候補を返すaction追加
受け取ったパラメータをもとにサジェストしたい文字列の配列を返すようにします。

user_controller.rb
  def autocomplete_company
    # params[:company]の値でUser.companyを前方一致検索、company列だけ取り出し、nilと空文字を取り除いた配列
    companies = User.by_company_like(autocomplete_params[:company]).pluck(:company).reject(&:blank?)
    render json: companies
    # レスポンスの例: ["てすと1会社","てすと2会社","てすと3会社"]
  end

  private

    def autocomplete_params
      params.permit(:company)
    end

ビュー

autocompleteのsourceに
サジェスト候補の配列を取得する関数をセット。

_form.html.slim
= form_with(model: @user, local: true) do |form|
 .form-group
  = form.label :company
  = form.text_field :company
  / id='user_company'で生成される

javascript:
  $(function() {
    const dataList = function(request, response) {
      $.ajax({
        url: '/users/autocomplete_company/' + request.term,
        dataType: 'json',
        type: 'GET',
        cache: true,
        success: function(data) {
          response(data);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
          response(['']);
        }
      });
    }

    // #user_companyの部分は必要に応じてidなり指定してください
    $('#user_company').autocomplete({
      source: dataList,
      autoFocus: true, // 自動的に先頭の項目にフォーカスするか
      delay: 300, // 入力してからサジェストが動くまでの時間(ms)
      minLength: 2 // 2文字入力しないとサジェストが動かない
    })
  });

テキストフィールドの内容に応じて、動的に内容を変える必要がなければ
dataListにサジェストしたい文字列の配列を直接入れればOKです!

javascript:
  $(function() {
    const dataList = ["こうほ1","こうほ2"];
  });

まとめ

jquery-uiを使って、サジェスト機能を実装しました。
今回は説明のため、Viewに直接javascriptを書いてますが
別ファイルにしたり、ヘルパーを切り出したりすると良いと思われます☺️

間違っているところがあればご指摘ください!

autocompleteのドキュメント

19
20
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
19
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?