Class: Headmin::Filter::Base

Inherits:
Object
  • Object
show all
Defined in:
app/models/headmin/filter/base.rb

Direct Known Subclasses

Association, AssociationCount, Boolean, Date, Field, Number, Search, Text

Constant Summary collapse

OPERATORS =

Constants

%w[eq not_eq gt gteq lt lteq between not_between in not_in matches does_not_match is_null is_not_null starts_with ends_with]
OPERATORS_CONVERT_TO =
{
  convert_to_range: %w[between not_between],
  convert_to_array: %w[in not_in in_all in_any],
  convert_to_value: %w[eq not_eq gt gteq lt lteq matches does_not_match is_null is_not_null starts_with ends_with]
}
QUERY_VALUE_CONVERT_TO =
{
  convert_value_to_match: %w[matches does_not_match],
  convert_to_starts: %w[starts_with],
  convert_to_ends: %w[ends_with]
}
QUERY_OPERATOR_CONVERT_TO =
{
  matches: %w[starts_with ends_with]
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attribute, params, association: nil) ⇒ Base

Methods



24
25
26
27
28
29
30
31
32
33
# File 'app/models/headmin/filter/base.rb', line 24

def initialize(attribute, params, association: nil)
  @attribute = association ? "#{association}_#{attribute}".to_sym : attribute
  @raw_value = params[@attribute]
  @association = association
  @instructions = []

  if params.key?(@attribute)
    parse(@raw_value)
  end
end

Instance Attribute Details

#attributeObject (readonly)

Returns the value of attribute attribute.



36
37
38
# File 'app/models/headmin/filter/base.rb', line 36

def attribute
  @attribute
end

#instructionsObject (readonly)

Returns the value of attribute instructions.



54
55
56
# File 'app/models/headmin/filter/base.rb', line 54

def instructions
  @instructions
end

#raw_valueObject (readonly)

Returns the value of attribute raw_value.



35
36
37
# File 'app/models/headmin/filter/base.rb', line 35

def raw_value
  @raw_value
end

Instance Method Details

#build_query(query, collection, instruction) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'app/models/headmin/filter/base.rb', line 79

def build_query(query, collection, instruction)
  query_operator = convert_to_query_operator(instruction[:operator])
  query_value = convert_to_query_value(instruction[:value], instruction[:operator])

  query_operator, query_value = process_null_operators(query_operator, query_value)

  model = collection.is_a?(Class) ? collection : collection.model

  if @association
    # Association attributes are passed through as {association}_{attribute}, so we need to transform this into {attribute}
    new_attribute = attribute.to_s.gsub("#{@association}_", "").to_sym
    new_model = model.reflect_on_association(@association)

    # In case the association cannot be found, raise a well defined error
    raise UnknownAssociation if new_model.nil?

    new_query = new_model.klass.arel_table[new_attribute].send(query_operator, query_value)
  else
    new_query = model.arel_table[attribute].send(query_operator, query_value)
  end

  query ? query.send(instruction[:conditional], new_query) : new_query
end

#cast_value(value) ⇒ Object



69
70
71
72
73
# File 'app/models/headmin/filter/base.rb', line 69

def cast_value(value)
  # This method has to be implemented by the child.

  raise NotImplementedMethodError, "Method cast_value has to be implemented by its child."
end

#conditionalsObject



46
47
48
# File 'app/models/headmin/filter/base.rb', line 46

def conditionals
  @instructions.map { |instruction| instruction[:conditional] }.compact
end

#display_value(value) ⇒ Object



75
76
77
# File 'app/models/headmin/filter/base.rb', line 75

def display_value(value)
  value
end

#is_i?(value) ⇒ Boolean

Returns:



103
104
105
106
107
108
109
110
111
# File 'app/models/headmin/filter/base.rb', line 103

def is_i?(value)
  # Regex: this selects signed digits (\d) only, it is then checked to the value, e.g.:
  # is_i?("3") = true
  # is_i?("-3") = true
  # is_i?("3a") = false
  # is_i?("3.2") = false

  /\A[-+]?\d+\z/.match(value)
end

#operatorsObject



42
43
44
# File 'app/models/headmin/filter/base.rb', line 42

def operators
  @instructions.map { |instruction| instruction[:operator] }.compact
end

#query(collection) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/models/headmin/filter/base.rb', line 56

def query(collection)
  return collection unless @instructions.any?

  query = nil

  @instructions.each do |instruction|
    query = build_query(query, collection, instruction)
  end

  collection = collection.joins(@association) if @association
  collection.distinct.where(query)
end

#string(display_values = []) ⇒ Object



50
51
52
# File 'app/models/headmin/filter/base.rb', line 50

def string(display_values = [])
  build_instructions_string(display_values)
end

#valuesObject



38
39
40
# File 'app/models/headmin/filter/base.rb', line 38

def values
  @instructions.map { |instruction| instruction[:value] }.compact
end