Using Ransack with HABTM

If you’re unfamiliar with Ransack, it’s basically an advanced search form generator for Rails. It allows you to add fields to the form for things like category_id_eq and title_cont and it will “magically” query the database.

The only real problem with Ransack is the lack of documentation. Almost every time I had a problem I ended up looking on Stack Overflow or through the Github Issues page. Both of those sites are easy to search through which wasn’t a hindrance, but it took a long time to figure out simple things.

One of those simple things, which I’m not the only one that had a problem with, was creating a select field for a has_many :through or has_and_belongs_to_many association.

The Setup

Here are the three models that I have in place. It’s a basic setup for has_many :through allowing multiple categories being assigned to products and vice versa. For more information take a look at Rails Guide on ActiveRecord associations.

# product.rb
class Product < ActiveRecord::Base
  has_many :categorizations
  has_many :categories, :through => :categorizations
end

# category.rb
class Category < ActiveRecord::Base
  has_many :categorizations
  has_many :products, :through => :categorizations
end

# categorization.rb
class Categorization < ActiveRecord::Base
  belongs_to :category
  belongs_to :product
end

The Ransack Way

For Ransack to pick up on the association you have to provide the “associated” models plural name. For instance, if we are building a search form for the products page then the field name would be categories_id_eq. Here’s an example form

<%= search_form_for @query do |f| %>
  <%= f.label :categories_id_eq, "Category" %>
  <%= f.collection_select :categories_id_eq, Category.order(:title), :id, :title %>

  <%= f.submit "Filter Products" %>
<% end %>