module Datagrid::Filters
Defines the accessible attribute that is used to filter the scope by the specified value with specified code.
class UserGrid < ApplicationGrid scope do User end filter(:name) filter(:posts_count, :integer) do |value| self.where(["posts_count >= ?", value]) end end
Each filter becomes a grid attribute.
To create a grid displaying all users with the name ‘John’ who have more than zero posts:
grid = UserGrid.new(posts_count: 1, name: "John") grid.assets # SELECT * FROM users WHERE users.posts_count > 1 AND name = 'John'
Filter blocks should always return a chainable ORM object (e.g., ‘ActiveRecord::Relation`) rather than an `Array`.
# Filter Block
Filter blocks should have at least one argument representing the value assigned to the grid object attribute:
filter(:name, :string) # { |value| where(name: value) }
You can pass additional arguments:
filter(:name, :string) { |value, scope| scope.where("name ilike ?", "%#{value}%") } filter(:name, :string) do |value, scope, grid| scope.where("name #{grid.predicate} ?", "%#{value}%") end
# Filter Types
Filters
perform automatic type conversion. Supported filter types include:
-
‘default`
-
‘date`
-
‘datetime`
-
‘enum`
-
‘boolean`
-
‘xboolean`
-
‘integer`
-
‘float`
-
‘string`
-
‘dynamic`
## Default
‘:default` - Leaves the value as is.
## Date
‘:date` - Converts value to a date. Supports the `:range` option to accept date ranges.
filter(:created_at, :date, range: true, default: proc { 1.month.ago.to_date..Date.today })
## Datetime
‘:datetime` - Converts value to a timestamp. Supports the `:range` option to accept time ranges.
filter(:created_at, :datetime, range: true, default: proc { 1.hour.ago..Time.now })
## Enum
‘:enum` - For collection selection with options like `:select` and `:multiple`.
filter(:user_type, :enum, select: ['Admin', 'Customer', 'Manager']) filter(:category_id, :enum, select: proc { Category.all.map { |c| [c.name, c.id] } }, multiple: true)
## Boolean
‘:boolean` - Converts value to `true` or `false`.
## Xboolean
‘:xboolean` - Subtype of `enum` filter that provides “Yes”, “No”, and “Any” options.
filter(:active, :xboolean)
## Integer
‘:integer` - Converts value to an integer. Supports the `:range` option.
filter(:posts_count, :integer, range: true, default: (1..nil))
## String
‘:string` - Converts value to a string.
filter(:email, :string)
## Dynamic
Provides a builder for dynamic SQL conditions.
filter(:condition1, :dynamic) filter(:condition2, :dynamic) UsersGrid.new(condition1: [:name, "=~", "John"], condition2: [:posts_count, ">=", 1]) UsersGrid.assets # SELECT * FROM users WHERE name like '%John%' and posts_count >= 1
# Filter Options
Options that can be passed to any filter:
-
‘:header` - Human-readable filter name (default: generated from the filter name).
-
‘:default` - Default filter value (default: `nil`).
-
‘:multiple` - Allows multiple values (default: `false`).
-
‘:allow_nil` - Whether to apply the filter when the value is `nil` (default: `false`).
-
‘:allow_blank` - Whether to apply the filter when the value is blank (default: `false`).
Example:
filter(:id, :integer, header: "Identifier") filter(:created_at, :date, range: true, default: proc { 1.month.ago.to_date..Date.today })
## Default Filter Options
Default options for all filters in a grid can be set using ‘default_filter_options`.
self.default_filter_options = { header: "" }
It can also accept a proc with the filter instance as an argument:
self.default_filter_options = ->(filter) { { header: I18n.t(filter.name, scope: 'filters') } }
# Localization
Filter labels can be localized or specified via the ‘:header` option:
filter(:created_at, :date, header: "Creation date") filter(:created_at, :date, header: proc { I18n.t("creation_date") })
Constants
- DEFAULT_FILTER_BLOCK
-
@!visibility private
- FILTER_TYPES
-
@!visibility private
Public Class Methods
Source
# File lib/datagrid/filters.rb, line 288 def initialize(...) self.filters_array = self.class.filters_array.clone filters_array.each do |filter| value = filter.default(self) self[filter.name] = value unless value.nil? end super end
@!visibility private
Datagrid::Core::new
Public Instance Methods
Source
# File lib/datagrid/filters.rb, line 298 def assets apply_filters(super, filters) end
@!visibility private
Datagrid::Core#assets
Source
# File lib/datagrid/filters.rb, line 353 def default_filter self.class.default_filter end
@!visibility private
Source
# File lib/datagrid/filters.rb, line 324 def filter_by(*filters) apply_filters(scope, filters.map { |f| filter_by_name(f) }) end
@return [Array<Object>] assets filtered only by specified filters
Source
# File lib/datagrid/filters.rb, line 319 def filter_by_name(name) self.class.filter_by_name(name) end
@return [Datagrid::Filters::BaseFilter, nil] filter object with the given name
Source
# File lib/datagrid/filters.rb, line 303 def filter_value(filter) self[filter.name] end
@return [Object] filter value for given filter definition
Source
# File lib/datagrid/filters.rb, line 308 def filter_value_as_string(name) filter = filter_by_name(name) value = filter_value(filter) if value.is_a?(Array) value.map { |v| filter.format(v) }.join(filter.separator) else filter.format(value) end end
@return [String] string representation of filter value
Source
# File lib/datagrid/filters.rb, line 346 def filters self.class.filters.select do |filter| filter.enabled?(self) end end
@return [Array<Datagrid::Filters::BaseFilter>] all currently enabled filters
Source
# File lib/datagrid/filters.rb, line 335 def select_all(filter) filter = find_select_filter(filter) self[filter.name] = select_values(filter) end
@return [void] sets all options as selected for a filter that has options
Source
# File lib/datagrid/filters.rb, line 330 def select_options(filter) find_select_filter(filter).select(self) end
@return [Array] the select options for the filter @raise [ArgumentError] if the filter doesn’t support select options
Source
# File lib/datagrid/filters.rb, line 341 def select_values(filter) find_select_filter(filter).select_values(self) end
@return [Array] all possible values for the filter
Protected Instance Methods
Source
# File lib/datagrid/filters.rb, line 371 def apply_filters(current_scope, filters) filters.inject(current_scope) do |result, filter| filter.apply(self, result, filter_value(filter)) end end
Source
# File lib/datagrid/filters.rb, line 359 def find_select_filter(filter) filter = filter_by_name(filter) unless filter.class.included_modules.include?(::Datagrid::Filters::SelectOptions) type = FILTER_TYPES.invert[filter.class].inspect raise( ::Datagrid::ArgumentError, "#{self.class.name}##{filter.name} with type #{type} can not have select options", ) end filter end