Class: Montage::QueryParser

Inherits:
Object
  • Object
show all
Includes:
Support
Defined in:
lib/montage/query_parser.rb

Constant Summary collapse

TYPE_MAP =
{
  is_i?: :to_i,
  is_f?: :to_f,
  is_s?: :to_s
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Support

#is_f?, #is_i?, #nillify

Constructor Details

#initialize(query) ⇒ QueryParser

Returns a new instance of QueryParser.



18
19
20
# File 'lib/montage/query_parser.rb', line 18

def initialize(query)
  @query = query
end

Instance Attribute Details

#queryObject (readonly)

Returns the value of attribute query.



10
11
12
# File 'lib/montage/query_parser.rb', line 10

def query
  @query
end

Instance Method Details

#get_column_name(part, splitter = " ") ⇒ Object

Parse the column name from the specific query part



24
25
26
# File 'lib/montage/query_parser.rb', line 24

def get_column_name(part, splitter = " ")
  part.downcase.split(splitter)[0].strip
end

#get_parts(str) ⇒ Object

Get all the parts of the query string

Raises:



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/montage/query_parser.rb', line 61

def get_parts(str)
  operator, montage_operator = get_query_operator(str)

  raise QueryError, "The operator you have used is not a valid Montage query operator" unless montage_operator

  column_name = get_column_name(str, operator)

  raise QueryError, "Your query has an undetermined error" unless column_name

  value = parse_part(parse_condition_set(str, operator))

  [column_name, montage_operator, value]
end

#get_query_operator(part) ⇒ Object

Grabs the proper query operator from the string



30
31
32
33
# File 'lib/montage/query_parser.rb', line 30

def get_query_operator(part)
  operator = Montage::Operators.find_operator(part)
  [operator.operator, operator.montage_operator]
end

#parseObject

Parse the clause into a Montage query



99
100
101
102
103
104
105
# File 'lib/montage/query_parser.rb', line 99

def parse
  if query.is_a?(Hash)
    parse_hash
  else
    parse_string
  end
end

#parse_condition_set(clause, splitter = " ") ⇒ Object

Extract the condition set from the given clause



37
38
39
# File 'lib/montage/query_parser.rb', line 37

def parse_condition_set(clause, splitter = " ")
  clause.split(/#{splitter}/i)[-1].strip
end

#parse_hashObject

Parse a hash type query



77
78
79
80
81
82
83
84
# File 'lib/montage/query_parser.rb', line 77

def parse_hash
  Hash[
    query.map do |key, value|
      new_key = value.is_a?(Array) ? "#{key}__in".to_sym : key
      [new_key, value]
    end
  ]
end

#parse_part(part) ⇒ Object

Parse a single portion of the query string



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/montage/query_parser.rb', line 43

def parse_part(part)
  parsed_part = JSON.parse(part) rescue part

  if is_i?(parsed_part)
    parsed_part.to_i
  elsif is_f?(parsed_part)
    parsed_part.to_f
  elsif parsed_part =~ /\(.*\)/
    to_array(parsed_part)
  elsif parsed_part.is_a?(Array)
    parsed_part
  else
    parsed_part.gsub(/('|')/, "")
  end
end

#parse_stringObject

Parse a string type query



88
89
90
91
92
93
94
95
# File 'lib/montage/query_parser.rb', line 88

def parse_string
  Hash[
    query.split(/\band\b(?=([^']*'[^']*')*[^']*$)/i).map do |part|
      column_name, operator, value = get_parts(part)
      ["#{column_name}#{operator}".to_sym, value]
    end
  ]
end

#to_array(value) ⇒ Object

Takes a string value and splits it into an array Will coerce all values into the type of the first type



110
111
112
113
114
# File 'lib/montage/query_parser.rb', line 110

def to_array(value)
  values = value.gsub(/('|\(|\))/, "").split(',')
  type = [:is_i?, :is_f?].find(Proc.new { :is_s? }) { |t| send(t, values.first) }
  values.map { |v| v.send(TYPE_MAP[type]) }
end