module Model::FilterBy

Public Instance Methods

filter_by(filters = {}) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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