Custom Filter Method
Overviewâ
We can add a custom filter method to filter records based on specific criteria. This is useful when the default filtering options do not meet the requirements. The custom filter method can be defined using the filter_with option.
Usageâ
The custom filter method is implemented using the filter dsl_method with the filter_with option. Below are the key elements and their usage:
Syntaxâ
filter :filter_name, :filter_type, filter_with: :custom_filter_method
Scope signatureâ
| Filter type | Scope arguments |
|---|---|
:search | (value) |
:single_select, :multi_select | (value, condition = nil) |
:date, :range | (value, condition = nil) |
condition is the operator selected in Advanced Filters, for example is_not or greater_than. It is nil when the scope is called from the standard filter bar. For date and range filters, value is the raw string ("2026-01-01 to 2026-01-31", "18 to 30", or a single value such as "18").
Lambda scopes enforce arity. A select, date, or range scope that does not accept condition raises ArgumentError.
Exampleâ
1. For Search:
class YourModel < ApplicationRecord
scope :custom_filter_method, ->(value) { where('column_name ILIKE ?', "%#{value}%") }
end
filter :filter_name, :search, filter_with: :custom_filter_method
2. For Single / Multi Select:
class User < ApplicationRecord
scope :by_company_country, lambda { |value, condition = nil|
left_joins(:company).ct_dropdown_filter_condition(column: :country, value:, condition:, table: 'companies')
}
end
filter :company_country, :multi_select, helper_method: :company_country_options, filter_with: :by_company_country
3. For Date and Range:
class User < ApplicationRecord
scope :by_company_size, lambda { |value, condition = nil|
left_joins(:company).ct_range_filter_condition(column: :employee_count, value:, condition:, table: 'companies')
}
end
filter :company_size, :range, filter_with: :by_company_size
Condition helpersâ
These helpers are available on every ActiveRecord model through CmAdmin::FilterConditions. table: defaults to the model's own table.
| Helper | Handles |
|---|---|
ct_dropdown_filter_condition(column:, value:, condition:, table:) | is, is_not, is_empty, is_not_empty. cm_empty maps to NULL |
ct_range_filter_condition(column:, value:, condition:, table:) | between, not_between, greater_than, less_than, greater_than_or_equal_to, less_than_or_equal_to, is, is_not, is_empty, is_not_empty |
If you write the logic by hand instead, handle is_empty / is_not_empty. They are called with a blank value.