We’ve been working on a new social networking site, and I’ve been integrating Searchlogic for the first time to help make searching for users and posts easier. I saw Searchlogic’s creator give a presentation at a Boston Ruby meetup, and I was pretty psyched to learn about the existence of this simple way to keep the code for this common task clean and DRY.
First, we needed a way for visitors to search for user profiles simply by the fields that are in the database. Easy! Searchlogic has this built-in.
In the view:
<% form_for @search, :html => {:method => 'post'} do |f| %>
Username: <%= f.text_field :login_like %>
First Name: <%= f.text_field :first_name_like %>
Last Name: <%= f.text_field :last_name_like %>
Bio: <%= f.text_field :bio_like %>
Career: <%= f.text_field :career_like %>
Education: <%= f.text_field :education_like %>
<%= submit_tag 'search' %>
<% end %>
And in the controller, where the real savings happens:
if request.post? @search = User.search(params[:search]) @users = @search.all else @search = User.search end
Searching on all the user’s fields, with just a couple lines of code!
In searching posts, we needed some slightly more complicated searches; we’re using acts_as_taggable_on_steroids and wanted users to be able to search for posts with particular tags, and we also wanted a way to use the post’s belongs_to association to allow users to search for posts entered by a particular user. Since Searchlogic allows us to define our own named scopes, we just need to add a couple of lines to the model to be ready to use the same tricks we used searching on database fields:
named_scope :has_tags, lambda { |tags|
Post.find_options_for_find_tagged_with(tags, :match_all => true)
}
named_scope :poster_login_like, lambda { |c| { :joins => ["LEFT OUTER JOIN users ON (users.id = posts.poster_id)"], :conditions => ['users.login LIKE ?', c]
}}
We also wanted searching for post content to include a search of the post body. So the view looks like this:
<% form_for @search, :html => {:method => 'post'} do |f| %>
Containing: <%= f.text_field :content_like %></p>
<p>Tagged with: <%= f.text_field :has_tags %></p>
<p>By Username: <%= f.text_field :poster_login_like %></p>
<%= submit_tag 'search' %>
<% end %>
And the controller has the same super-simple:
if request.post?
@search = Post.search(params[:search])
@posts = @search.all
else
@search = Post.search
end
This is one of the things I love about working with Rails — thanks to all the great gems and plugins out there, we can do complex stuff with just a few lines of code rather than re-inventing the wheel.

Clara