Module: Model::FilterBy

Defined in:
lib/resourcify/model/filter_by.rb

Instance Method Summary collapse

Instance Method Details

#filter_by(filters = {}) ⇒ Object



3
4
5
6
7
8
9
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/resourcify/model/filter_by.rb', line 3

def filter_by(filters = {})
  records = self
  columns_hash = self.columns_hash

  def sanitize_value(field, value)
    field_type = columns_hash[field].type
    if field_type == :datetime || field_type == :date
      value = Time.parse(value).to_s(:db)
    end
    value
  end
  
  def query_params(q)
    ops = { eq: '=', lt: '<', gt: '>', lte: '<=', gte: '>=', ne: '!='}
    field, op, value = q[:name], (q[:op] || 'eq').to_sym, q[:value]

    if ops[op]
      ["#{field} #{ops[op]} ?", sanitize_value(field, value)]
    elsif op == :in
      vals = value.split(',')
      vals = vals.map { |e| sanitize_value(field, e) }
      ["#{field} IN (?)", vals]
    elsif op == :nin
      vals = value.split(',')
      vals = vals.map { |e| sanitize_value(field, e) }
      ["#{field} NOT IN (?)", vals]
    elsif op == :between
      vals = value.split('||')
      query_string = '(' + vals.map { |e| "(#{field} >= ? AND #{field} <= ?)" }.join(' OR ') + ')'
      vals = vals.map { |e| e.split('|') }.flatten
      vals = vals.map { |e| sanitize_value(field, e) }
      vals.unshift(query_string)
      vals
    elsif op == :like
      like_key = (ActiveRecord::Base.connection.adapter_name == "PostgreSQL")? 'ILIKE' : 'LIKE'
      vals = value.split('|').map { |val| "%#{val}%" }
      query_string = '(' + vals.map { |e| "#{field} #{like_key} ?" }.join(' OR ') + ')'
      vals.unshift(query_string)
      vals
    else
      ["#{field} = ?", sanitize_value(field, value)]
    end
  end

  filters.map do |key, value|
    name, op = key.to_s.split('.')
    { name: name, op: op, value: value }
  end.group_by do |q|
    q[:name]
  end.select do |key|
    columns_hash.include? key
  end.map do |key, value|
    qparams = value.map { |e| query_params(e) }
    qstring = qparams.map { |e| e.first }.join(' OR ')
    qparams.map { |e| e[1..-1] }.flatten(1).unshift(qstring)
  end.each do |qparam|
    records = records.where(*qparam)
  end
  
  records
end

#query_params(q) ⇒ Object



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
40
41
42
43
44
45
# File 'lib/resourcify/model/filter_by.rb', line 15

def query_params(q)
  ops = { eq: '=', lt: '<', gt: '>', lte: '<=', gte: '>=', ne: '!='}
  field, op, value = q[:name], (q[:op] || 'eq').to_sym, q[:value]

  if ops[op]
    ["#{field} #{ops[op]} ?", sanitize_value(field, value)]
  elsif op == :in
    vals = value.split(',')
    vals = vals.map { |e| sanitize_value(field, e) }
    ["#{field} IN (?)", vals]
  elsif op == :nin
    vals = value.split(',')
    vals = vals.map { |e| sanitize_value(field, e) }
    ["#{field} NOT IN (?)", vals]
  elsif op == :between
    vals = value.split('||')
    query_string = '(' + vals.map { |e| "(#{field} >= ? AND #{field} <= ?)" }.join(' OR ') + ')'
    vals = vals.map { |e| e.split('|') }.flatten
    vals = vals.map { |e| sanitize_value(field, e) }
    vals.unshift(query_string)
    vals
  elsif op == :like
    like_key = (ActiveRecord::Base.connection.adapter_name == "PostgreSQL")? 'ILIKE' : 'LIKE'
    vals = value.split('|').map { |val| "%#{val}%" }
    query_string = '(' + vals.map { |e| "#{field} #{like_key} ?" }.join(' OR ') + ')'
    vals.unshift(query_string)
    vals
  else
    ["#{field} = ?", sanitize_value(field, value)]
  end
end

#sanitize_value(field, value) ⇒ Object



7
8
9
10
11
12
13
# File 'lib/resourcify/model/filter_by.rb', line 7

def sanitize_value(field, value)
  field_type = columns_hash[field].type
  if field_type == :datetime || field_type == :date
    value = Time.parse(value).to_s(:db)
  end
  value
end