Skip to content

Filters

Steven Steffen edited this page Aug 13, 2024 · 2 revisions

The filter class is simply a class extending the Refine::Filter which provides all the business logic for your filter. You should have a Filter class defined for every core model you will want to provide filter behavior for. Best practice is to place all filters in the root app directory under filters.

app/
├─ assets/
├─ controllers/
├─ filters/
│  └─ contacts_filter.rb
├─ helpers/
├─ models/
└─ views/
config/
db/

The Filter Class

The filter class has several important components. Here is an example of an EmployeesFilter

class EmployeesFilter < Refine::Filter
  include Refine::Conditions
  @@default_stabilizer = Refine::Stabilizers::UrlEncodedStabilizer

  def initial_query
    Contact.all
  end

  def conditions
    [
      TextCondition.new("name"),
      DateCondition.new("created_at"),
      NumericCondition.new("id"),
    ]
  end
end

Initial Query

The initial_query method is the starting point for every filter. This allows you, as the developer, to add restrictions into the base query that cannot be changed by the end user. In many cases you can simply use an empty model query:

def initial_query
  Employee.all
end

This works well in many cases, but not all of them. For instance, if you want to scope the entire filter by company_id, you can do so in the initial_query:

def initial_query
  Employee.where(company_id: 5)
end

Or maybe you want to add in a scope:

def initial_query
  Employee.active
end

You're welcome to do anything you want in this method, as long as you return an ActiveRecord::Relation.

Conditions

Conditions are where you define what your users can filter on. If you wanted to let your users filter based on the employee's name, you could add a "name" condition.

def conditions
  [
    TextCondition.new('name', 'Name')
  ]
end

The package comes with many conditions out of the box that you can use to build your perfect filter. To learn more about conditions, jump to the TODO: conditions overview page.

Table

The table is simple the name of the arel table backing your model. It's simply Model.arel_table. This defaults to initial_query.model.arel_table which should work for the majority of cases.

def table
  Employee.arel_table
end

Category Order (Optional)

If your filter is using the Category Meta, you can define the method category_order in your filter. This expects an array of strings that match the list of categories defined in your meta. If this is not defined, Refine will simply order them in the order in which it processes the conditions array. Whether this is sorted using Refine::Rails.configuration.option_condition_ordering or just in the flat array list order as defined in the Filter class.

def category_order
    [
      "Contact Attributes",
      "Contact Activity",
      "Custom Attributes"
    ]
  end

Filter Generator

Refine provides a rails-like generator script for creating new filter classes which was demonstrated in the installation instructions. This is meant as a scaffolding helper and should be updated with more complex conditions.

rails generate filter [lowercased model name] [attribute_name:condition_type] [attribute_name:condition_type] ...

In the installation instructions we used the example

rails generate filter contact name:text created_at:date id:numeric

contact is the lowercased model name so it corresponds with a model called Contact.

name:text is the contact's name attribute which we want to make a TextCondition

created_at:date is the contact's created_at attribute which we want to make a DateCondition

id:numeric is the contact's id attribute which we want to make a NumericCondition