Rails Implementation of Search with Autocomplete

Rails implementation of search with autocomplete

Use Twitter typeahead. There are some examples here:

http://twitter.github.com/typeahead.js/examples/

Twitter typeahead and all the information you need is available from https://github.com/twitter/typeahead.js/

How to use

The use depends on the data you are going to have as 'suggested'. For example, if it is static data (always going to be the same) you can implement it this way:

$('input.typeahead').typeahead({
local: ['suggestion1', 'suggestion2', 'suggestion3',...., 'suggestionN']
#The typeahead is going to load suggestions from data in local.
});

If the data changes and it came from a model or a db table then you can try:

Controller:
def load_suggestions
@suggestions = MyModel.select(:name) or MyModel.find(:all, conditions: [...]) #Select the data you want to load on the typeahead.
render json: @suggestions
end

JS file:
$('input.typeahead').typeahead([
{
prefetch: 'https://www.mipage.com/suggestion.json' #route to the method 'load_suggestions'
#This way, typeahead will prefecth the data from the remote url
}
]);

Best auto complete/suggest for a search form in rails 3

jqueryui is a great resource.

here is a demo of autocomplete, you can view the source to see how to implement on your server.
http://jqueryui.com/demos/autocomplete/

the javascript sends a term=TERM to your controller. Mine is setup like this:

def autocomplete
@movies= Movie.select("id, title").where("title LIKE ?", "#{params[:term]}%").limit(20)
@hash = []
@movies.each do |movie|
@hash << {"label" => movie.title, "id" => movie.id}
end
render :json => @hash
end

customize to how you see fit.

Ruby on Rails - Simple Form autocomplete association search

autocomplete_source is expecting an array or a URL that when called returns JSON with the results that match the query. http://api.jqueryui.com/autocomplete/#option-source

Right now you have

  <%= f.input :user_name, as: :search, data: 
{autocomplete_source: User.pluck(:name)} %>

Thats probably going to return a string for javascript. So you could change it to something like:

  <%= f.input :user_name, as: :search, data: 
{autocomplete_source: User.pluck(:name).to_json} %>

And then parse that JSON when setting up your autocomplete:

jQuery ->
$('#task_user_name').autocomplete
source: JSON.parse($('#task_user_name').data('autocomplete-source'))

In the long run though (when you have a lot of users) this will impact the load time of your page significantly. You should really instead follow that railscast and put a URL as the autocomplete source:

  <%= f.input :user_name, as: :search, data: 
{autocomplete_source: users_path} %>

Make sure to add the json render path to the index action on your users controller.

If your index action is used for other things too you can use respond_to:

# users_controller
def index
@users = User.order(:name)
@users = @users.where("name like ?", "%#{params[:term]}%") if params[:term]

respond_to do |format|
format.html # index.html.erb
format.json { render :json => @users.map(&:name) }
end
end

Autocomplete multiple fields with jquery in Rails 5

I've managed to make it work using a different method with the rails-jquery-autocomplete gem:

https://github.com/risuiowa/rails-jquery-autocomplete/

Using the

autocomplete_field

turned out to be much easier to implement.
Example:

form_for @product do |f|
f.autocomplete_field :brand_name, autocomplete_brand_name_products_path
end

Implement autocomplete on MongoDB

As suggested by @Thilo, you can use several ideas including prefixing.

The most important thing is to have very quick request (because you want autocomplete to feel instaneous). So you have to use query which will use properly indexes.

With regexp : use /^prefix/ (the important thing is the ^ to specify the beginning of line which is mandatory to make the query use index).

The range query is good too : { $gt : 'jhc', $lt: 'jhd' } }

More complicated but faster : you can store prefix-trees in mongo (aka tries) with entries like :

 {usrPrefix : "anna", compl : ["annaconda", "annabelle", "annather"]}
{usrPrefix : "ann", compl : ["anne", "annaconda", "annabelle", "annather"]}

This last solution is very fast (if indexes on compl of course) but not space efficient at all. You know the trade-off you have too choose.

Rails gem rails3-jquery-autocomplete: How do I query multiple fields

Your pseudo attribute works only on records already retrieved, but it has no bearing on searching for records. Probably the easiest solution is a named named scope like:

 scope :search_by_name, lambda { |q|
(q ? where(["first_name LIKE ? or last_name LIKE ? or concat(first_name, ' ', last_name) like ?", '%'+ q + '%', '%'+ q + '%','%'+ q + '%' ]) : {})
}

Thus, a call like:

Person.search_by_name(params[:q]) 

will return an appropriate result set. It will also return all entries if no param was passed (or more specifically, this scope will add nothing extra), making it an easy drop-in for the index action.

Is it possible to get autocomplete for a rails application in text editors, not only text fields

The answer of abstraktor gave me a good starting point, but there were some missing parts. So I developed an example on github: jquery-autocomplete-inner

Here is the complete source code of the example (no HTML), and some explanation:

$().ready(function() {
// search only, if the regexp matches
var cities = [
"Amsterdam", "Stuttgart", "Singapore", "Madrid", "Barcelona", "Hamburg",
"Esslingen", "Berlin", "Frankfurt", "Essingen", "Straßburg", "London",
"Hannover", "Weil am Rhein", "Tuttlingen", "München", "Marsaille", "Paris",
"Manchester", "Rome", "Neapel", "New York", "Brasil", "Rio de Janeiro"
];
// Defines for the example the match to take which is any word (with Umlauts!!).
function _leftMatch(string, area) {
return string.substring(0, area.selectionStart).match(/[\wäöüÄÖÜß]+$/)
}

function _setCursorPosition(area, pos) {
if (area.setSelectionRange) {
area.setSelectionRange(pos, pos);
} else if (area.createTextRange) {
var range = area.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}

$("#citites").autocomplete({
position: { my : "right top", at: "right bottom" },
source: function(request, response) {
var str = _leftMatch(request.term, $("#citites")[0]);
str = (str != null) ? str[0] : "";
response($.ui.autocomplete.filter(
cities, str));
},
//minLength: 2, // does have no effect, regexpression is used instead
focus: function() {
// prevent value inserted on focus
return false;
},
// Insert the match inside the ui element at the current position by replacing the matching substring
select: function(event, ui) {
//alert("completing "+ui.item.value);},
var m = _leftMatch(this.value, this)[0];
var beg = this.value.substring(0, this.selectionStart - m.length);
this.value = beg + ui.item.value + this.value.substring(this.selectionStart, this.value.length);
var pos = beg.length + ui.item.value.length;
_setCursorPosition(this, pos);
return false;
},
search:function(event, ui) {
var m = _leftMatch(this.value, this);
return (m != null )
}
});
})
  • First the data of the examples, some cities (mostly German)
  • A helper function to extract the matching substring left from the cursor, named _leftMatch
  • A helper function copied mostly from jQuery Set Cursor Position in Text Area
  • Then in the usage of autocomplete the following points:

    • Search only when the substring (_leftMatch) before the cursor position matches the defined regexpression (in my example /[\wäöüÄÖÜß]+$/ --> all german work characters).
    • Filter the source things by using the request - response variation and filtering there by the substring (as in the other examples of autocomplete with multiple values
    • Replace the matching substring with the selection from the user and ensure that the cursor is positioned right after that.

If you want to take a look, download the zip-file from the GitHup repository and start the local example under examples/cities-local.html.



Related Topics



Leave a reply



Submit