Archive for April, 2009
RAILS + ThinkingSphinx + 2 Models = Search Results for both
Posted by Chris Sund in Rails Stuff on April 25th, 2009
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.

