Skip to content

How to build a simple ajax search in Ruby on Rails

Posted on 17 July 2006

I've just implemented a simple ajax search on my site and i'm going to explain how I did it.

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!

Update - 29th Dec 06

Since this article was written, I've updated my site and adjusted the way the search works. So keep in mind that the end result will not be exactly the same.

View the snippets archive ››

14 comments made

fulvio commented on 12 Jun 07 at 23:38

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 ?

Paul commented on 13 Jun 07 at 03:19

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!

Taras commented on 16 Aug 07 at 12:18

Great thing, Really helpful. Thank you very much.

aaron commented on 17 Sep 07 at 15:48

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

Paul commented on 17 Sep 07 at 15:55

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.

aaron commented on 17 Sep 07 at 21:18

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

thanks!

it works great.

aaron commented on 24 Sep 07 at 08:42

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

Paul commented on 24 Sep 07 at 09:08

Try changing your conditions to “fname LIKE ? and lname LIKE ?”

The key word being ‘and’ instead of ‘or’

aaron commented on 24 Sep 07 at 13:07

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

Cody commented on 13 Nov 07 at 08:29

Yeah

Jack Kinsella commented on 07 Apr 08 at 18:11

Excellent Tutorial! Works like a charm!

ty commented on 26 Jul 08 at 00:50

tyt

fgh commented on 26 Jul 08 at 00:51

gfhfgh

gvuhjj commented on 29 Jul 08 at 01:57

gtnytnm

Got something to say?

About

Paul is a web developer for Kyanmedia web agency. He's lucky enough to write in Ruby on Rails full-time and uses this site to post snippets of code.

Contact

my name at gmail.com

More snippets

Take a look in the archive

Need a website?

Contact my employer. Make sure to check out our portfolio of work.

Hosting

I recommend hostingrails.com