Class: Admin::Base::FilterBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/admin/base/filter_builder.rb

Constant Summary collapse

MIN_SEARCH_LENGTH =

Matches the index search box's existing floor: below this, apply_search leaves the scope untouched rather than emitting a near-useless single/double-character ILIKE. search_predicate (below) is where this now lives, since it's shared with ResourcesController#search.

3

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(resource_class, params) ⇒ FilterBuilder

Returns a new instance of FilterBuilder.



15
16
17
18
# File 'lib/admin/base/filter_builder.rb', line 15

def initialize(resource_class, params)
  @resource_class = resource_class
  @params = params
end

Instance Attribute Details

#paramsObject (readonly)

Returns the value of attribute params.



13
14
15
# File 'lib/admin/base/filter_builder.rb', line 13

def params
  @params
end

#resource_classObject (readonly)

Returns the value of attribute resource_class.



13
14
15
# File 'lib/admin/base/filter_builder.rb', line 13

def resource_class
  @resource_class
end

Class Method Details

.search_predicate(index_config, term) ⇒ Array(String, String)?

Builds the shared ILIKE-over-searchable_fields predicate -- the exact logic apply_search below uses for the index's own search box -- extracted so ResourcesController#search (the searchable_select endpoint) can reuse it verbatim instead of growing a second, divergent search path over the same whitelist.

The term is always returned as a value to be bound ("%term%"), never interpolated into the SQL text -- only the (whitelisted) field names from index_config.searchable_fields go into the conditions string, exactly as apply_search has always built it. That keeps this safe against SQL metacharacters in term: whatever a caller passes ends up as a single bound parameter, not part of the query text.

Returns nil when no predicate should be applied at all: no index config, no declared searchable fields, a blank term, or a term shorter than MIN_SEARCH_LENGTH. What a nil predicate means is left to the caller -- apply_search treats it as "don't filter" (falls back to the unfiltered scope, correct for an index filter box), while ResourcesController#search treats it as "no results" (correct for a raw JSON data endpoint, which must never hand back the unfiltered table just because the query was blank/too short or the resource has no searchable fields to check).

Parameters:

Returns:

  • (Array(String, String), nil)

    [sql_conditions, "%term%"]



63
64
65
66
67
68
69
70
71
# File 'lib/admin/base/filter_builder.rb', line 63

def self.search_predicate(index_config, term)
  return nil if index_config.nil?
  return nil if term.blank?
  return nil if index_config.searchable_fields.empty?
  return nil if term.to_s.length < MIN_SEARCH_LENGTH

  conditions = index_config.searchable_fields.map { |field| "#{field} ILIKE :search" }.join(" OR ")
  [ conditions, "%#{term}%" ]
end

Instance Method Details

#apply(scope) ⇒ Object



20
21
22
23
24
25
# File 'lib/admin/base/filter_builder.rb', line 20

def apply(scope)
  scope = apply_search(scope)
  scope = apply_filters(scope)
  scope = apply_sort(scope)
  scope
end

#filter_paramsObject



27
28
29
30
31
32
33
34
# File 'lib/admin/base/filter_builder.rb', line 27

def filter_params
  return {} unless index_config

  permitted_keys = [ :search, :sort, :sort_direction, :page ]
  permitted_keys += index_config.filters_list.map(&:name)

  params.permit(*permitted_keys).to_h.symbolize_keys
end