Hey everyone,
This is my first Ruby on Rails article, and I’m excited to contribute something to the community (I hope). I decided to write this article due to the fact I had a heck of a time finding this information myself. I’m not claiming to know everything here, just everything I know. I am open for suggestions, and comments. I am simply trying to help someone avoid all the hassle I had as a noob with “ThinkingSphinx/Rails”. Here’s what it’s all about.
(PS, I’m using PostgreSQL for my database, but that shouldn’t matter with this example)
Lets say you need the ability to search at least 2 models in your project and have ThinkingSphinx (TS) return your search results with information from both models. In my case I have an Account model with account information, and then a whole seperate Name model with the name information that is associated with each account.
Example…
account.rb
has_many :names, :dependent => :destroy
# Thinking Sphinx Search Indexes
define_index do
indexes s_account, :sortable => true
indexes s_account_no
indexes names.name, :as => :account_name
end
name.rb
belongs_to :account
# Thinking Sphinx Search Indexes
define_index do
indexes account.s_account, :sortable => true
indexes account.s_account_no
indexes name, :as => :account_name
end
A misconception I had when I started was the fact that I had to setup my search criteria in either my “Accounts” controller or my “Name” controller. This in fact isn’t true. After a bunch of trial and error and misunderstanding I found out that you can setup your search criteria in a seperate controller and model. I called mine “Results”. So to keep everything simple I will outline my rails files below, and try to provide some insight as to why I did it that way. The truth of the matter is however…. I did it this way because it worked. I would love comments from anyone that feels they have a better way.
I already outlined my model files above, so here’s the rest of the info…
ROUTES FILE (I added the following line)
APPLICATION TEMPLATE
viewslayoutsapplication.html.erb
<div id=”search”>
<%= text_field_tag :search, params[:search], :class => ‘text’ %>
<%= submit_tag ‘Search’, :class => ‘button’ %>
</div>
CONTROLLERS:
accounts_controller
I did nothing to this controller to make it work.
names_controller
again, I did nothing to this controller
results_controller (I created this specifically for searching)
def search
@results = ThinkingSphinx::Search.search(params[:search],
:classes => [Account,Name])
respond_to do |format|
format.html #calls the search.html.erb (viewsresultssearch.html.erb)
end
end
end
VIEW FILES
viewsresultssearch.html.erb
<% if result.class == Account %>
<br><%= render :partial => ‘accounts/results’, :locals => {:account => result } %><br>
<% elsif result.class == Name %>
<%= render :partial => ‘names/results’, :locals => {:name => result } %><br><br>
<% end %>
<%- end -%>
<%= will_paginate @results %>
viewsaccounts_results.html.erb
viewsnames_results.html.erb
When I was trying to find this information it didn’t make sense to me that I had to render a partial per model. After I set it up, and was able to see the results it seemed to work great. I just got it all setup, and I’m sure I will do some tweaking, but I was eager to post this blog before I got too lazy, or decided I wasn’t qualified yet to post anything about ThinkingSphinx. I’m not representing myself as qualified in this area I simply want to add one more resource for someone else to look at. If you have a better idea, or would like to add a comment, please do so.


#1 by peter at November 23rd, 2009
Great article. You have exactly what I am looking for.
Only question is where did you put the viewslayoutsapplication.html.erb, viewsresultssearch.html.erb and viewsaccounts_results.html.erb?
#2 by Lawrence at April 8th, 2010
thank you so much for this. It would’ve taken me way to long to figure out on my own!