Ransack needs <Model> Associations explicitly allowlisted as searchable – Ransack

by
Ali Hasan
concurrent-ruby ransack ruby-on-rails rubygems

Quick Fix: Create ApplicationRecord.rb which should extends from ActiveRecord::Base. Override the ransackable_attributes and ransackable_associations methods within that class. This will allow Ransack to search across all associations for all models that inherit from ApplicationRecord.

The Problem:

Ransack requires explicitly allowlisting model associations for searching. Upon installing the ‘ipaddress’ gem, models started throwing an error stating that no searchable associations were defined. To resolve this, each model needs to define a ransackable_associations method to specify which associations are searchable. However, manually defining this method for every model can be tedious. The task is to find a dynamic way to automate this process for all models.

The Solutions:

Solution 1: Use a Custom ApplicationRecord Class

To resolve this issue for all models, you can create a custom ApplicationRecord class that includes the required methods:

class ApplicationRecord < ActiveRecord::Base
  primary_abstract_class
  self.abstract_class = true

  def self.ransackable_attributes(auth_object = nil)
    column_names + _ransackers.keys
  end

  def self.ransackable_associations(auth_object = nil)
    reflect_on_all_associations.map { |a| a.name.to_s } + _ransackers.keys
  end
end

This class should be placed in the app/models/application_record.rb file.

Additionally, if you're using the impressionist gem for model impressions, you may need to modify its initializer to include the following method:

# config/initializers/impressionist.rb

module Impressionist
  def self.ransackable_associations(auth_object = nil)
    super + %w[impressionable]
  end
end

Solution 2: Disable Ransack's Association Whitelisting

To disable Ransack's requirement for explicit association whitelisting, revert to the pre-Ransack 4.0 code by defining the ransackable_associations and ransackable_attributes methods in the ApplicationRecord model:

class ApplicationRecord &lt; ActiveRecord::Base
  # ...

  def self.ransackable_associations(auth_object = nil)
    @ransackable_associations ||= reflect_on_all_associations.map { |a| a.name.to_s }
  end

  def self.ransackable_attributes(auth_object = nil)
    @ransackable_attributes ||= column_names + _ransackers.keys + _ransack_aliases.keys + attribute_aliases.keys
  end
end

This will enable Ransack to search through all associations and attributes without requiring explicit whitelisting.

Q&A

Why Ransack needs associations explicitly allowlisted as searchable and what change was introduced in ransack 4?

Ransack 4 introduced a change that requires explicit whitelisting for associations and attributes to improve security.

How to make ransack work for all models instead of defining ransackable_associations for each model?

You can create an ApplicationRecord class and define ransackable_associations and ransackable_attributes methods there.

How to revert ransack to pre-4.0 behavior?

You can disable the new behavior by reverting ransackable_associations and ransackable_attributes methods in ApplicationRecord to the pre-4.0 code.

Video Explanation:

The following video, titled "Implementing Search in Rails 7 using Ransack gem - YouTube", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

Hello Friends In this video, you will how to implement a search feature in a rails application using Ransack Gem.