Full Text Search With Ruby on Rails

I'm working on something and I needed a search functionality so I did check out my options. I did not prefer MySQL's full text search functionality as I don't want MySQL to deal with it where there are tools created only for that. I did take a look at [Sphinx](http://sphinxsearch.com/), [Solr](http://lucene.apache.org/solr/) and [ElasticSearch](http://www.elasticsearch.org/). Among three of them I did prefer Solr. Luckily, kudos to [Mat Brown](http://outofti.me/) he had created a Solr gem for Ruby called [Sunspot](https://github.com/outoftime/sunspot) and a Ruby on Rails plugin on top of it called Sunspot Rails. In order to make it compact, I will explain all this with creating a sample Rails application.
Creating the Rails Application
----------
Let's create a new Rails application and generate a model and its scaffold.
rails new rails_fulltext_search -d mysql
cd rails_fulltext_search
sudo bundle install
rails g scaffold Company name:string city:string state:string country:string
Installing Sunspot Rails
----------
Like installing any other Rails plugin or Ruby gem with Rails, we simply add `gem 'sunspot_rails'` to your Gemfile and run `bundle install`. Start Solr instance with `rake sunspot:solr:start`
echo "gem 'sunspot_rails'" >> Gemfile
sudo bundle install
rake sunspot:solr:start
A note: If you get an error complaining like "libxml2 not found" from nokogiri, you can do `sudo apt-get install libxml2-dev` and install it on Ubuntu.
Indexing the Model
----------
Now that we have a Company model that has 'name, city, state, country' fields. How do we make Solr index it? The following is the answer.
class Company < ActiveRecord::Base
searchable do
text :name
string :city
string :state
string :country
end
end
What does this `text` and `string` do here? When we tell Sunspot that `name` is a `text` field, it automatically tokenizes it, applies default filters and downcases it and we use the `keywords()` method to find indexed `text` data however when we use `string`, it does not do anything and the data marked as string can only be searched as is by the `with()` method.
By default, whenever we create new Company objects, they will be indexed automatically. What about our current data? You can index them by running `rake sunspot:solr:reindex` command.
How to Implement Search Functionality
----------
Let's add a search action in our companies_controller and create the corresponding view in `/app/views/companies/` called `search.html.erb`.
# goes in app/controllers/companies_controller.rb
def search
if params[:commit]
@companies = Company.search do
if params[:name]; keywords(params[:name]); end
[:city, :state, :country].each do |field|
if params[field] != ""; with(field, params[field]); end
end
end.results
end
end
We implement both searching and displaying results in one action. It's not a must or must not do. Do whatever pleases you. The following is our corresponding view.
# app/views/companies/search.html.erb

Search companies

'get') do %>

Search results

No companies found.
Now add this entry `get '/companies/search'` to your `config/routes.rb` before `resources :companies` line.
Congratulations! You now have a Rails application using Solr for full text search! The full application is available at [my github repositories](http://github.com/mengu/rails_fulltext_sample). We are not over here. In the next post, I will explain how to paginate the search results.
Please feel free to ask any questions you have and you can [follow me on twitter](http://www.twitter.com/mengukagan).