How to build a simple ajax search in Ruby on Rails
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.
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
14 comments made
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 ?
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!
Great thing, Really helpful. Thank you very much.
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
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.
Thanks! I haven’t dealt with partials and the location (shared directory) messed me up.
thanks!
it works great.
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
Try changing your conditions to “fname LIKE ? and lname LIKE ?”
The key word being ‘and’ instead of ‘or’
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
Yeah
Excellent Tutorial! Works like a charm!
tyt
gfhfgh
gtnytnm
Got something to say?