Introduction

Implementing proper search is a must for most applications. Fortunately, thanks to Ransack, you can easily add search to your application. In this article, we will show you how to implement search in your Rails application. Note that we are now using Rails 5 for our articles and Ruby 2.3.1. If you are using Rails 4.2, you should be able to follow along pretty easily just by modifying the commands we write. If you have any questions, feel free to leave a comment in the comments section. Let's get started.

Rails Application Setup

The first thing we need to do is add Ransack to the Gemfile. Open up your Gemfile and add in the line listed below.

Gemfile:

gem 'ransack'

Now run a bundle install to install the gem.

Terminal Commands:

bundle install

Great, now let's create a model called Product to use for our example. The Product model will have just one field, name. Run the commands below to create this model now.

Terminal Commands:

rails g model Product name
rails db:migrate

Now we need to create some seed data. Open up your db/seeds.rb file and modify it to look like the code listed below.

db/seeds.rb:

Product.delete_all

Product.create!(name: 'Apples')
Product.create!(name: 'Oranges')
Product.create!(name: 'Strawberries')
Product.create!(name: 'Bananas')
Product.create!(name: 'Blueberries')
Product.create!(name: 'Pears')
Product.create!(name: 'Grapes')

Now let's seed the database, run the command below to add the products to your database. Run the command below to do this now.

Terminal Commands:

rails db:seed

Now let's create a controller called Products and add an index method to it. We will use the index to both display and search for products. Run the command below to do this now.

Terminal Commands:

rails g controller Products index

Now we need to modify our routes file. We need to set a site root and add an entry for our products path. Open up your config/routes.rb file and modify it so that it looks like the code listed below.

config/routes.rb:

Rails.application.routes.draw do
  root to: 'products#index'
  resources :products
end

Now we need to open up our Products controller and add in some search functionality. Open up your app/controllers/products_controller.rb file and modify it so that it looks like the code listed below.

app/controllers/products_controller.rb:

class ProductsController < ApplicationController
  def index
    @q = Product.ransack(params[:q])
    @products = @q.result
  end
end

The code above uses ransack to search for the contents of params[:q]. We will cover the params[:q] object a bit more closely in a moment, for now let's talk about the second line. @q.results returns a regular Active Record Relation, so we can potentially do joins, and even pagination if we wanted to. For now we simply return the result.

Now let's build the view. Open up the app/views/products/index.html.erb file and modify it so that it looks like the code listed below.

app/views/products/index.html.erb:

<h1>Products</h1>

<%= search_form_for @q do |f| %>
  <%= f.label :name_cont %>
  <%= f.search_field :name_cont %>
  <%= f.submit %>
<% end %>

<table>
  <thead>
    <tr>
      <th><%= sort_link(@q, :name) %></th>
    </tr>
  </thead>
  <tbody>
    <% @products.each do |product| %>
      <tr>
        <td>Name</td>
      </tr>
    <% end %>
  </tbody>
</table>

You'll notice a couple of things going on here. First of all, search_form_for is a specific search form helper provided by Ransack. This search form helper builds a search query which gets passed (the params[:q] we mentioned earlier) to Ransack. The next thing you'll notice is a search_field form helper that creates a text field named name_cont. the _cont is a special search predicate that tells ransack we wish to search for names that CONTain our query. There are other search predicates as well such as start (stars with), end (ends with), eq (equals), and more. You can even do less than and greater than.

You can also combine database fields. For example, let's say we wanted to search both the first name and last name of a person. You would simple do:


Person.ransack(first_name_or_last_name_cont: 'Jackson')

This would generate a query that would search for someone either with the first name OR the last name of jackson.

Sorting

Ransack also includes support for sorting your results. To implement this, simply open up your app/views/products/index.html.erb file and modify it so that it looks like the code listed below.


<h1>Products</h1>

<%= search_form_for @q do |f| %>
  <%= f.label :name_cont %>
  <%= f.search_field :name_cont %>
  <%= f.submit %>
<% end %>

<table>
  <thead>
    <tr>
      <th><%= sort_link(@q, :name) %></th>
    </tr>
  </thead>
  <tbody>
    <% @products.each do |product| %>
      <tr>
        <td><%= product.name %></td>
      </tr>
    <% end %>
  </tbody>
</table>

If you start and visit your local Rails development server you will notice that the table header is now clickable and you can sort either ascending or descending. Pretty handy!

Well that wraps it up for this basic intro to Ransack. If you want to find out more, be sure to visit The Ransack Homepage and check out their wiki. If you have any questions or comments, feel free to leave them below. If you aren't already a premium member, I'd encourage you to sign up, as we are going to be doing some really cool stuff in the near future. Thanks for reading!