How to build a simple ajax search in Ruby on Rails

Posted on 17 July 2006

A simple, quick and easy way to get an ajax search built in Ruby on Rails.

In my view:


<%= start_form_tag({}, {:id => "search"}) %>  
	   <%= text_field_tag("query", params[:query], :autocomplete => "off" ) %>
    <%= end_form_tag %>
    
    <%= observe_field 'query',  :frequency => 2,
								:update => "search_results",								
								:url => {:controller => "articles", :action => "search"},
								:with => "query" %>

<div id="search_results">
   (initial page content in here)
</div>

So I have a search box with the id query that is being observered for changes every two seconds by the observe_field method. In order to use the observe_field you will need the following line in your document header:

<%= javascript_include_tag :defaults %>

This just includes all the prototype and scriptaculous javascript required for the ajax.

In my controller I have a search action:


def search    
    session[:query] = params[:query].strip if params[:query]
    
    if session[:query] and request.xhr?
      @articles = Article.find(:all, :conditions => ["content LIKE ?", "%#{session[:query]}%"], :order => "title ASC")     
      render :partial => "shared/searchresults", :layout => false, :locals => {:searchresults => @articles} 
    end
  end

First I've set the query in the session. Although I havn't implemented any pagination for my search, using the session would enable me to do that if I decided to implement it.

Next I check if a query has been sent and if the request was an ajax call. I then search all my articles with the search query and render a partial for the results. Passing the articles found in the local variables.

My partial looks like this:


<% if searchresults.length == 0 %>

	<p>Sorry! No articles found...</p>

<% elsif params[:query] == "" %>
    
    <p>You must enter a search term.</p>

<% else %>
	
	<ul>
	<% for article in searchresults %>	   
	    <li><%= link_to article.title , article_url(:id => article.id) %></li>
	<% end %>
	</ul>

<% end %>

It's pretty straight forward, I just have a couple of checks in case the search params aren't going to return any useful results.

Once you have all the above in place then that should be it!

About Paul

Paul works for Kyan web design agency in Surrey, UK as a Ruby on Rails developer.

Follow Paul on Twitter

Email: paulsturgess [at] gmail.com

Read more articles in the archive →

Comments...

  • Your RSS implementation is perfect. I use that on my site. However I tried to implement this AJAX search and I'm not sure of what you mean by your partial containing that bit of code?

    /app/views/article/_search.rhtml ?

    fulvio at 12 Jun 07 at 23:38

  • The observe_field tag :url option indicates the action to perform when a user enters a query into the search box.

    The :update option indicates where the result of that action should appear. In this case it will be in the html element with the id 'search_results'.

    The :with option passes the search term into the search action.

    You will see that the search action renders the partial 'searchresults' with no layout - this is so that it can be placed directly into the 'search_results' div.

    Hope that all makes sense!

    Paul at 13 Jun 07 at 03:19

  • Great thing, Really helpful. Thank you very much.

    Taras at 16 Aug 07 at 12:18

  • I almost have it working, but I'm a little confused on where to put the partial (filename?). Here is the error I am getting once I type in something in the search field:

    No rhtml, rxml, rjs or delegate template found for shared/app/views

    Suggestions?

    thanks

    aaron at 17 Sep 07 at 15:48

  • Hi Aaron,

    The search results partial in my example is stored in a folder called shared in app/views and the filename is '_searchresults.rhtml'.

    Hope that helps,

    Paul.

    Paul at 17 Sep 07 at 15:55

  • Thanks! I haven't dealt with partials and the location (shared directory) messed me up.

    thanks!

    it works great.

    aaron at 17 Sep 07 at 21:18

  • it's me again.... is it possible to search for multiple things in one search? I have this working:

    @people = Person.find(:all, :conditions => ["fname LIKE ? or lname LIKE ?", "%#{session[:query]}%", "%#{session[:query]}%"], :order => "fname ASC")

    but it returns first name or last name, not both (as it should, that is what I am telling it to do).

    thanks for any suggestions

    aaron at 24 Sep 07 at 08:42

  • Try changing your conditions to "fname LIKE ? and lname LIKE ?"

    The key word being 'and' instead of 'or'

    Paul at 24 Sep 07 at 09:08

  • that doesn't work...if you start typing and only type in the letter 'o' ...it will display people that have the name like 'bob hope' because they both have the letter 'o'

    i don't want to bug you too much....what i have now works enough for me. thanks

    aaron at 24 Sep 07 at 13:07

  • Yeah

    Cody at 13 Nov 07 at 08:29

  • Excellent Tutorial! Works like a charm!

    Jack Kinsella at 07 Apr 08 at 18:11

  • please help me to call this ajax function only if search word is more than 3 characters

    thanks

    joseph at 09 Dec 08 at 09:49

  • cool, thanks

    CaDs at 11 Dec 08 at 13:20

  • This is awesome, thanks a ton!

    Robin at 25 Mar 09 at 00:12

  • very good one! thanks

    Bob at 28 Sep 09 at 10:17

  • thankyou, will you help me with ajax pagiantion

    swetha at 28 Oct 09 at 01:42

  • I have found a problem. I'm using rails 2.3.5 and i find this error : undefined method `start_form_tag' . Due to error, i changed my code like this : <% form_tag({}, {:id => "search"}) %>
    <%= text_field_tag("query", params[:query], :autocomplete => "off" ) %>
    <%= submit_tag "Search!" %>
    <% end %>. Then, i still get an error:
    compile error
    app/views/accounts/index.html.erb:42: syntax error, unexpected kENSURE, expecting $end. It seems the parameter on form_tag is not appropriate. Any solution?? Will be really appreciate so much if you have the latest searching source code on rails latest version.

    Haryadi at 05 Jan 10 at 21:51

  • I'm sorry. The problem is solved. Looks like i forget to add "do", before closing the form_tag.

    Haryadi at 05 Jan 10 at 21:55

  • hey how to achieve pagination with this can u tell that

    sharath at 06 Aug 10 at 05:30

Got something to say?