Upgrading Sorting and Filtering in Rails with Ransack


Rails Ransack
search filtering tutorial

Upgrading Sorting and Filtering in Rails with Ransack

Ever tried building search functionality in Rails and ended up with a messy controller full of where clauses? I’ve been there! Let me show you how Ransack can save you hours of work and make your search code actually readable.

What is Ransack?

Ransack is a gem that handles search and filtering for you. Instead of writing tons of ActiveRecord queries, you just tell Ransack what you want to search for, and it does the heavy lifting.

Setup (Rails 7.0)

Add it to your Gemfile:

# Gemfile
gem 'rails', '~> 7.0.3'
gem 'ransack', '~> 2.6'
bundle install

Let’s Build an Article Search

Here’s a simple Article model we’ll use for our example:

# app/models/article.rb
class Article < ApplicationRecord
  belongs_to :author, class_name: 'User'
  belongs_to :category

  enum status: { draft: 0, published: 1, archived: 2 }
end

The Old Way vs The Ransack Way

Without Ransack (The Painful Way)

Look at all this code just for basic search:

# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def index
    @articles = Article.all
    
    # Title search
    if params[:title].present?
      @articles = @articles.where("title ILIKE ?", "%#{params[:title]}%")
    end
    
    # Status filter
    if params[:status].present?
      @articles = @articles.where(status: params[:status])
    end
    
    # Author filter  
    if params[:author_id].present?
      @articles = @articles.where(author_id: params[:author_id])
    end
    
    # And this goes on and on...
  end
end

With Ransack (The Easy Way)

# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def index
    @q = Article.ransack(params[:q])
    @articles = @q.result.includes(:author, :category)
  end
end

That’s it! Just 3 lines instead of 30+.

The Search Form

<!-- app/views/articles/index.html.erb -->
<%= search_form_for @q do |f| %>
  <%= f.search_field :title_cont, placeholder: "Search by title" %>
  
  <%= f.select :status_eq, options_for_select([
    ['All Statuses', ''],
    ['Draft', 'draft'], 
    ['Published', 'published'],
    ['Archived', 'archived']
  ]) %>
  
  <%= f.collection_select :author_id_eq, User.all, :id, :name, 
      { prompt: 'All Authors' } %>
  
  <%= f.submit "Search" %>
<% end %>

<!-- Easy sorting links -->
<%= sort_link(@q, :title, "Title") %>
<%= sort_link(@q, :created_at, "Date") %>

Cool Ransack Tricks

Want to search by author name? Easy!

<%= f.search_field :author_name_cont, placeholder: "Search by author name" %>

Different Search Types

Ransack has lots of built-in search options:

<!-- Contains (default) -->
<%= f.search_field :title_cont, placeholder: "Title contains..." %>

<!-- Starts with -->
<%= f.search_field :title_start, placeholder: "Title starts with..." %>

<!-- Equals exactly -->
<%= f.search_field :title_eq, placeholder: "Title equals..." %>

<!-- Date ranges -->
<%= f.date_field :created_at_gteq, placeholder: "From date" %>
<%= f.date_field :created_at_lteq, placeholder: "To date" %>

Why Ransack is Awesome

Less Code, More Features

  • Without Ransack: 30+ lines of messy controller code
  • With Ransack: 3 clean lines that do more

It’s Secure by Default

Ransack handles SQL injection protection for you. No more worrying about sanitizing user input!

Easy Sorting

<!-- Just add this and sorting works -->
<%= sort_link(@q, :title, "Title") %>
<%= sort_link(@q, :created_at, "Date") %>

Keep It Safe

You should tell Ransack which fields are okay to search:

# app/models/article.rb
class Article < ApplicationRecord
  def self.ransackable_attributes(auth_object = nil)
    %w[title content status created_at]
  end

  def self.ransackable_associations(auth_object = nil)
    %w[author category]
  end
end

Performance Tip

Always include your associations to avoid N+1 queries:

@articles = @q.result.includes(:author, :category)

Wrapping Up

Ransack turns complicated search code into something simple and readable. Instead of spending hours writing custom search logic, you can focus on building the features that matter.

The best part? It handles all the tricky stuff like SQL injection protection and parameter parsing automatically. Give it a try on your next Rails project - you’ll wonder how you ever built search without it!