Skip to content
treydock edited this page May 7, 2019 · 2 revisions

scoped_search can autocomplete a search query, returning lists of fields and possible values to the user for selection in a search UI.

Model autocompletion

Every scoped_search-enabled model has a .complete_for method that takes the partial search string and returns an array of possible searches.

At first it returns a list of possible field names and prefix operators:

> User.complete_for('')
=> [" first_name ", " last_name ", " not", " has"]

Then with the field name supplied, it can supply operators:

> User.complete_for('first_name ')
=> ["first_name  = ", "first_name  != ", "first_name  ~ ", "first_name  !~ ", "first_name  ^ ", "first_name  !^ "]

And with an operator, it can supply values:

> User.complete_for('first_name =')
=> ["first_name = John", "first_name = Jane"]

Customize search filter, in this example all returned values will be filtered by current user:

> model.complete_for(params[:search], value_filter: { user_id: current_user.id })

jQuery integration

A scopedSearch function is added via the asset pipeline to jQuery to add autocompletion support to text inputs using a categorized autocomplete.

Setup

To use the auto completer JavaScript-based UI you'll need to include jquery-ui. There are several ways to include jquery-ui, for example, add to the Gemfile:

gem 'jquery-rails'
gem 'jquery-ui-rails'

Usage

To activate autocompletion on all elements with the autocomplete-input class, call:

$(".autocomplete-input").scopedSearch();

scopedSearch() takes an options hash with these options:

Unless source is given, the element should have a data-url attribute set to an AJAX-capable URL, that should return results using model.complete_for.

Basic example

In the view:

<%= text_field_tag("search", value,
                   :class => 'autocomplete-input form-control',
                   :autocomplete => 'off',
                   :placeholder  => 'Search ..',
                   :'data-url'   => autocomplete_user_path)
%>

On the page load in application JS:

//= require jquery-ui/completer
$(function() {
  $(".autocomplete-input").scopedSearch();
});

In your application.css, require the corresponding CSS module:

*= require jquery-ui/completer

In the controller:

def autocomplete
  begin
    model = controller_name.classify.constantize
    @items = model.complete_for(params[:search])
    @items = @items.map do |item|
      category = (['and','or','not','has'].include?(item.to_s.sub(/^.*\s+/,''))) ? _('Operators') : ''
      part = item.to_s.sub(/^.*\b(and|or)\b/i) {|match| match.sub(/^.*\s+/,'')}
      completed = item.to_s.chomp(part)
      {:completed => CGI.escapeHTML(completed), :part => CGI.escapeHTML(part), :label => item, :category => category}
    end
  rescue ScopedSearch::QueryNotSupported => e
    @items = [{:error => e.to_s}]
  end
  render :json => @items
end
Clone this wiki locally