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:
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.
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
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.
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.
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.
To sum up I would like to provide you with advantages and disadvantages lists of ransack gem.
- code looks very simple and easy to maintain;
- fast and easy way to build search and sort functionality;
- flexible search conditions (predicates);
- associations search;
- elastic search integration.
- poor PostgreSQL data types support;
As for me ransack is awesome tool and I encourage you to give it a shot at your future projects.