How to Create Search Form with Ransack

We have to take care of routine programming tasks sometimes. You can't do anything about it. Motivation guides tell us to look for something special in this kind of tasks or think outside the box resolving them. But when your project is like a rocket science and you successfully implement the toughest features, looking at a ticket called "Add search to products page inside admin panel" makes your eyes bleed. The good thing is you don’t have to take care of UI/UX. You should just make agile and powerful tool for products page. Of course, manager will be proud if you minimize the most expensive resource - the time. So how we should do it? You can keep a gist with some table and search form template for index page. But I would like to show you a different way.

Within this tutorial we will use Ransack gem. To install it, simply add to your Gemfile:

   gem 'ransack'

Ransack showtime

Ransack allows you to build both simple and advanced search and sort functionality for your index page without developing monstrous where's or raw SQL.

To use it, just add to your controller:

@q = Product.ransack(params[:q])
@events = @q.result(distinct: true)

Ransack has a cool search_form_for helper. So, the Ransack search form in your view will look like:

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

As you can see it's very easy to create search form with Ransack. Search will look for particular ID of the Product. Pretty cool, isn’t it? Let's say you want to add another field to search for.

<%= f.search_field :name_eq %>

Now you are able to search for products with a specific name. At this point you may say that this kind of query can be easily built with ActiveRecord and you are right for 100%. But this is the place where Ransack search predicates come.

Predicates

There are lots of useful predicates. Let's take a look at cont predicate. It allows us to build LIKE-query. To add another search field, you can use this:

<%= f.search_field :description_cont %>

Also, Ransack has predicates which allow working easily with numbers and dates. Here is how to find products which were created within some range

<%= f.search_field :created_at_gteq %>
<%= f.search_field :created_at_lteq %>

Here we can see gteq and lteq predicates which stand for "Greater Than or EQual to" and "Less Than or EQual to" respectively.

Here you can learn more about predicates.

You can add a custom search method by ransack predicates and create almost any type of search functionality that can be required in our Rails applications. Still, in some specific cases extra development may be needed.

Sorting columns

Now we can enhance the index table (if we have one, of course). In most cases we need cool sortable columns and Ransack has sort_link helper that allows to pass additional options.

Let’s assume our products are listed as a table. In this case the view will look like:

<table>
  <tr>
    <th><%= sort_link @q, :id, default_order: :desc %></th>
    <th><%= sort_link @q, :name %></th>
    <th><%= sort_link @q, :description %></th>
    <th><%= sort_link @q, :created_at %></th>
  </tr>

  <% @products.each do |product| %>
    <tr>
      <td><%= product.id %></td>
      <td><%= product.name %></td>
      <td><%= product.description %></td>
      <td><%= product.created_at %></td>
    </tr>
  <% end %>
</table>

As you can see the search predicates are applied to sort_link helper fields exactly in the same way as for search form.

Generally this is enough for a simple index page. It looks pretty, user is able to search and sort the items. But there is an Advanced at the top of the article. So here is the one of the coolest features of ransack gem.

Associations search

Let’s play around with Ransack advanced search and make a more complex search query, e.g. "Search products of the owner which name includes ...". Here is how to add search field to do so:

<%= f.search_field :owner_first_name_cont %>

Same for sorting links:

 <th><%= sort_link @q, :owner_first_name_cont %></th>

Associations search feature works with polymorphic associations too.

Conclusion

In conclusion, let me provide you with a list of advantages and disadvantages of using the ransack gem.

Advantages:

  • Simple and easy-to-maintain code
  • Fast and easy way to build search and sort functionality
  • Flexible search conditions using predicates
  • Ability to search through associations
  • Integration with Elasticsearch

And the biggest disadvantage is limited support for PostgreSQL data types.

So in my opinion, ransack is an excellent tool and I highly recommend giving it a try in your future projects.