Class: Insights::API::Common::Filter

Inherits:
Object
  • Object
show all
Defined in:
lib/insights/api/common/filter.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

INTEGER_COMPARISON_KEYWORDS =
["eq", "not_eq", "gt", "gte", "lt", "lte", "nil", "not_nil"].freeze
STRING_COMPARISON_KEYWORDS =
["contains", "contains_i", "eq", "not_eq", "eq_i", "not_eq_i", "starts_with", "starts_with_i", "ends_with", "ends_with_i", "nil", "not_nil"].freeze
ALL_COMPARISON_KEYWORDS =
(INTEGER_COMPARISON_KEYWORDS + STRING_COMPARISON_KEYWORDS).uniq.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, raw_filter, api_doc_definition, extra_filterable_attributes = {}) ⇒ Filter

Instantiates a new Filter object

Parameters:

model

An AR model that acts as the base collection to be filtered

raw_filter

The filter from the request query string

api_doc_definition

The documented object definition from the OpenAPI doc

extra_filterable_attributes

Attributes that can be used for filtering but are not documented in the OpenAPI doc. Something like ‘=> {“type” => “string”}`

Returns:

A new Filter object, call #apply to get the filtered set of results.



26
27
28
29
30
31
32
# File 'lib/insights/api/common/filter.rb', line 26

def initialize(model, raw_filter, api_doc_definition, extra_filterable_attributes = {})
  @raw_filter                  = raw_filter
  @api_doc_definition          = api_doc_definition
  @arel_table                  = model.arel_table
  @extra_filterable_attributes = extra_filterable_attributes
  @model                       = model
end

Instance Attribute Details

#api_doc_definitionObject (readonly)

Returns the value of attribute api_doc_definition.



9
10
11
# File 'lib/insights/api/common/filter.rb', line 9

def api_doc_definition
  @api_doc_definition
end

#applyObject (readonly)

Returns the value of attribute apply.



9
10
11
# File 'lib/insights/api/common/filter.rb', line 9

def apply
  @apply
end

#arel_tableObject (readonly)

Returns the value of attribute arel_table.



9
10
11
# File 'lib/insights/api/common/filter.rb', line 9

def arel_table
  @arel_table
end

#extra_filterable_attributesObject (readonly)

Returns the value of attribute extra_filterable_attributes.



9
10
11
# File 'lib/insights/api/common/filter.rb', line 9

def extra_filterable_attributes
  @extra_filterable_attributes
end

#modelObject (readonly)

Returns the value of attribute model.



9
10
11
# File 'lib/insights/api/common/filter.rb', line 9

def model
  @model
end

#queryObject



34
35
36
# File 'lib/insights/api/common/filter.rb', line 34

def query
  @query ||= filter_associations.present? ? model.left_outer_joins(filter_associations) : model
end

Class Method Details

.association_attribute_properties(api_doc_definitions, raw_filter) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/insights/api/common/filter.rb', line 88

def self.association_attribute_properties(api_doc_definitions, raw_filter)
  return {} if raw_filter.blank?

  association_attributes = compact_filter(raw_filter).keys.select { |key| key.include?('.') }.compact.uniq
  return {} if association_attributes.blank?

  association_attributes.each_with_object({}) do |key, hash|
    association, attr = key.split('.')
    hash[key] = api_doc_definitions[association.singularize.classify].properties[attr.to_s]
  end
end

.compact_filter(filter) ⇒ Object

Compact filters to support association filtering

Input:  {"source_type"=>{"name"=>{"eq"=>"rhev"}}}
Output: {"source_type.name"=>{"eq"=>"rhev"}}

Input:  {"source_type"=>{"name"=>{"eq"=>["openstack", "openshift"]}}}
Output: {"source_type.name"=>{"eq"=>["openstack", "openshift"]}}


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/insights/api/common/filter.rb', line 65

def self.compact_filter(filter)
  result = {}
  return result if filter.blank?
  return filter unless filter.kind_of?(Hash) || filter.kind_of?(ActionController::Parameters)

  filter = Hash(filter.permit!) if filter.kind_of?(ActionController::Parameters)

  filter.each do |ak, av|
    if av.kind_of?(Hash)
      av.each do |atk, atv|
        if !ALL_COMPARISON_KEYWORDS.include?(atk)
          result["#{ak}.#{atk}"] = atv
        else
          result[ak] = av
        end
      end
    else
      result[ak] = av
    end
  end
  result
end