Class: RESTFramework::Filters::SearchFilter

Inherits:
BaseFilter
  • Object
show all
Defined in:
lib/rest_framework/filters/search_filter.rb

Instance Method Summary collapse

Methods inherited from BaseFilter

#_polymorphic_columns, _safe_query_value?, #initialize

Constructor Details

This class inherits a constructor from RESTFramework::Filters::BaseFilter

Instance Method Details

#_get_fieldsObject



2
3
4
5
6
7
# File 'lib/rest_framework/filters/search_filter.rb', line 2

def _get_fields
  # Always return a list of strings; `@controller.readable_columns` already does.
  @controller.class.search_fields&.map(&:to_s) || (
    @controller.readable_columns & RESTFramework.config.search_columns
  )
end

#filter_data(data) ⇒ Object

Filter data according to the request query parameters.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rest_framework/filters/search_filter.rb', line 10

def filter_data(data)
  search = @controller.request.query_parameters[@controller.class.search_query_param]

  # Reject nested-hash inputs like `?search[evil]=x` (Rack parses these into a
  # Hash, which `sanitize_sql_like` can't accept).
  return data unless search.is_a?(String)

  if search.present?
    if fields = self._get_fields.presence
      # MySQL doesn't support casting to VARCHAR, so we need to use CHAR instead.
      data_type = if data.connection.adapter_name =~ /mysql|trilogy/i
        "CHAR"
      else
        # Sufficient for both PostgreSQL and SQLite.
        "VARCHAR"
      end

      conn = data.connection
      like_op = @controller.class.search_ilike ? "ILIKE" : "LIKE"
      return data.where(
        fields.map { |f|
          "CAST(#{conn.quote_column_name(f)} AS #{data_type}) #{like_op} ?"
        }.join(" OR "),
        *([ "%#{ActiveRecord::Base.sanitize_sql_like(search)}%" ] * fields.length),
      )
    end
  end

  data
end