rad_core_rails 0.7.5 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95f6475b2b10bb6d51c5b4ad3feb7ebe08404663230abcae5278e81babe5e189
4
- data.tar.gz: 90bfdddfeda70290d119eaad3bb4cdd35afc593e04a1d7d7a0c71736567b6710
3
+ metadata.gz: 82f95dfd6c84c8aa3594f89b742563c9d2d07c0637ae18432acabd352c6ff088
4
+ data.tar.gz: bf435325dc6b733c186167a643c07330d10da47fa165328b14465109986af93e
5
5
  SHA512:
6
- metadata.gz: 5406cb277bf3591e979e14adb5aef5f92370483cd8dce83fb1cd78c333f0c57ebd9a9de3a586272c649738ee44fe5a32a2d7f08b3ab54b545c914366033e1bb9
7
- data.tar.gz: 20950b080d702d04bde47999be305945643acdf50d078f9d0fe05a50108656ad648f453f652d248e4e0980b9df980f9e84cb0ae8b84b5b366597bffb4616f05b
6
+ metadata.gz: 5e47b6b0a09ff8f6b77c8b97b59664e8b03180e1f1ed461b6a37eef2a0bd59431195055c33e565c2244c0ffa56708dfd186b35dcc2c9f3ccfbb5acfa66a39f1c
7
+ data.tar.gz: 2205ff6ff6494d0f770b69f896b26e5075c23da826ca964f2edafd2dba7f3cee7f0add929538ec755fc65f44e10142847ba269223c1acae2f9f4c7637fcaec83
@@ -24,15 +24,16 @@ module RadCoreRails
24
24
  @filter_manifest || {}.with_indifferent_access
25
25
  end
26
26
 
27
- def create_filters(search, filters)
27
+ def create_filters(filters)
28
28
  query = []
29
29
  args = []
30
- clause, arguments = generate_search_clause(search)
31
- query << clause
32
- arguments.each do |arg|
33
- args << arg
34
- end
35
- filters.map do |filter|
30
+ # clause, arguments = generate_search_clause(search)
31
+ # query << clause
32
+ # arguments.each do |arg|
33
+ # args << arg
34
+ # end
35
+ filters.map do |raw_filter|
36
+ filter = raw_filter.with_indifferent_access
36
37
  begin
37
38
  clause, arguments = filter_manifest[filter[:key]].call(filter)
38
39
  query << clause
@@ -46,7 +47,8 @@ module RadCoreRails
46
47
  [query.reject(&:blank?).join(' AND '), args]
47
48
  end
48
49
 
49
- def generate_search_clause(search)
50
+ def generate_search_clause(filter)
51
+ search = filter[:values][0]
50
52
  search_clause = ['', []]
51
53
 
52
54
  if search.present? && searchable_columns.is_a?(Array)
@@ -57,23 +59,28 @@ module RadCoreRails
57
59
  or_args = [] # SQL from sanitized_or_terms
58
60
  or_clause = [] # table columns SQL for all the OR terms
59
61
 
60
- phrases_to_exclude = search.scan(/-"([^"]*)"/) # e.g. -"Phrase to exclude"
61
- phrases_or = search.scan(/\+"([^"]*)"/) # e.g. +"Phrase for OR"
62
+ phrases_or = search.scan(/\+"([^"]*)"/) # e.g. +"Phrase for OR"
63
+ # remove 'or' phrases from search if any
64
+ phrases_or.each { |phrase| search.gsub!('+"' + phrase.first.to_s + '"', '') } if phrases_or.any?
62
65
 
66
+ phrases_to_exclude = search.scan(/-"([^"]*)"/) # e.g. -"Phrase to exclude"
63
67
  # remove excluded phrases from search if any
64
68
  if phrases_to_exclude.any?
65
- phrases_to_exclude.each {|phrase| search.gsub!('-"' + "#{phrase.first}" + '"', '')}
69
+ phrases_to_exclude.each { |phrase| search.gsub!('-"' + phrase.first.to_s + '"', '') }
66
70
  end
67
71
 
68
- # remove 'or' phrases from search if any
69
- if phrases_or.any?
70
- phrases_or.each {|phrase| search.gsub!('+"' + "#{phrase.first}" + '"', '')}
71
- end
72
+ phrases_and = search.scan(/"([^"]*)"/) # e.g. "Phrase for AND"
73
+ # remove 'and' phrases from search if any
74
+ phrases_and.each { |phrase| search.gsub!('"' + phrase.first.to_s + '"', '') } if phrases_and.any?
72
75
 
73
76
  # extract 'and' terms, remove casing, and add ILIKE '%' comparisons
74
77
  sanitized_and_terms = search.split(' ')
75
78
  .reject { |term| term.include?('+') || term.include?('-') }
76
79
  .map { |term| '%' + term.downcase.strip + '%' }
80
+ # add 'and' phrase terms, remove casing, and add ILIKE '%' comparisons
81
+ if phrases_and.any?
82
+ sanitized_and_terms += phrases_and.flatten.map { |phrase| '%' + phrase.downcase.strip + '%' }
83
+ end
77
84
 
78
85
  # extract 'or' terms, remove casing, and add ILIKE '%' comparisons
79
86
  sanitized_or_terms = search.split(' ')
@@ -81,9 +88,7 @@ module RadCoreRails
81
88
  .map { |term| '%' + term[1, term.length].downcase.strip + '%' }
82
89
 
83
90
  # add 'or' phrase terms, remove casing, and add ILIKE '%' comparisons
84
- if phrases_or.any?
85
- sanitized_or_terms += phrases_or.flatten.map{|phrase| '%' + phrase.downcase.strip + '%'}
86
- end
91
+ sanitized_or_terms += phrases_or.flatten.map { |phrase| '%' + phrase.downcase.strip + '%' } if phrases_or.any?
87
92
 
88
93
  # extract excluded terms, remove casing, and add NOT ILIKE '%' comparisons
89
94
  sanitized_excluded_terms = search.split(' ')
@@ -92,7 +97,8 @@ module RadCoreRails
92
97
 
93
98
  # add excluded phrase terms, remove casing, and add NOT ILIKE '%' comparisons
94
99
  if phrases_to_exclude.any?
95
- sanitized_excluded_terms += phrases_to_exclude.flatten.map{|phrase| '%' + phrase.downcase.strip + '%'}
100
+ sanitized_excluded_terms += phrases_to_exclude.flatten
101
+ .map { |phrase| '%' + phrase.downcase.strip + '%' }
96
102
  end
97
103
 
98
104
  # loop through sanitized_and_terms to find all possible columns.
@@ -100,7 +106,7 @@ module RadCoreRails
100
106
  columns = []
101
107
  # all possible columns where this should be searched
102
108
  searchable_columns.each do |col|
103
- columns.push("(LOWER(#{col}) ILIKE ?)")
109
+ columns.push("(COALESCE(LOWER(#{col}), '') ILIKE ?)")
104
110
  and_args.push sanitized_term
105
111
  end
106
112
  and_clause.push '(' + columns.join(' OR ') + ')'
@@ -110,7 +116,7 @@ module RadCoreRails
110
116
  columns = []
111
117
  # all possible columns where this should be searched
112
118
  searchable_columns.each do |col|
113
- columns.push("(LOWER(#{col}) NOT ILIKE ?)")
119
+ columns.push("(COALESCE(LOWER(#{col}), '') NOT ILIKE ?)")
114
120
  excluded_args.push sanitized_term
115
121
  end
116
122
  excluded_clause.push '(' + columns.join(' AND ') + ')'
@@ -120,34 +126,28 @@ module RadCoreRails
120
126
  columns = []
121
127
  # all possible columns where this should be searched
122
128
  searchable_columns.each do |col|
123
- columns.push("(LOWER(#{col}) ILIKE ?)")
129
+ columns.push("(COALESCE(LOWER(#{col}), '') ILIKE ?)")
124
130
  or_args.push sanitized_term
125
131
  end
126
132
  or_clause.push '(' + columns.join(' OR ') + ')'
127
133
  end
128
134
 
129
- if or_clause.empty? && and_clause.empty? && excluded_clause.empty?
130
- return ['', []]
131
- end
135
+ return ['', []] if or_clause.empty? && and_clause.empty? && excluded_clause.empty?
132
136
 
133
- if or_clause.empty? && excluded_clause.empty?
134
- return ['(' + and_clause.join(' AND ') + ')', and_args]
135
- end
137
+ return ['(' + and_clause.join(' AND ') + ')', and_args] if or_clause.empty? && excluded_clause.empty?
136
138
 
137
- if and_clause.empty? && excluded_clause.empty?
138
- return ['(' + or_clause.join(' OR ') + ')', or_args]
139
- end
139
+ return ['(' + or_clause.join(' OR ') + ')', or_args] if and_clause.empty? && excluded_clause.empty?
140
140
 
141
- if or_clause.empty? && and_clause.empty?
142
- return ['(' + excluded_clause.join(' AND ') + ')', excluded_args]
143
- end
141
+ return ['(' + excluded_clause.join(' AND ') + ')', excluded_args] if or_clause.empty? && and_clause.empty?
144
142
 
145
143
  if or_clause.empty?
146
- return ['((' + and_clause.join(' AND ') + ') AND (' + excluded_clause.join(' AND ') + '))', and_args + excluded_args]
144
+ return ['((' + and_clause.join(' AND ') + ') AND (' + excluded_clause.join(' AND ') + '))',
145
+ and_args + excluded_args]
147
146
  end
148
147
 
149
148
  if and_clause.empty?
150
- return ['((' + or_clause.join(' OR ') + ') AND (' + excluded_clause.join(' AND ') + '))', or_args + excluded_args]
149
+ return ['((' + or_clause.join(' OR ') + ') AND (' + excluded_clause.join(' AND ') + '))',
150
+ or_args + excluded_args]
151
151
  end
152
152
 
153
153
  if excluded_clause.empty?
@@ -155,14 +155,14 @@ module RadCoreRails
155
155
  end
156
156
 
157
157
  search_clause = [
158
- '((' +
159
- and_clause.join(' AND ') +
160
- ') AND (' +
161
- or_clause.join(' OR ') +
162
- ') AND (' +
163
- excluded_clause.join(' AND ') +
164
- '))',
165
- and_args + or_args + excluded_args
158
+ '((' +
159
+ and_clause.join(' AND ') +
160
+ ') AND (' +
161
+ or_clause.join(' OR ') +
162
+ ') AND (' +
163
+ excluded_clause.join(' AND ') +
164
+ '))',
165
+ and_args + or_args + excluded_args
166
166
  ]
167
167
  end
168
168
 
@@ -179,18 +179,93 @@ module RadCoreRails
179
179
  end
180
180
 
181
181
  def generate_model_clause(column_name, filter, optional_exclusion_clause = nil)
182
- str = if optional_exclusion_clause.present? && filter[:option] == '!='
183
- optional_exclusion_clause
184
- else
185
- # probably should fix this.
186
- # somtimes we arent sending a filter option, so just default it to =
187
- "(#{column_name} #{filter[:option] || '='} ANY(ARRAY[?]))"
188
- end
189
- args = [filter[:values]]
182
+ if optional_exclusion_clause.present? && filter[:option] == '!='
183
+ str = optional_exclusion_clause
184
+ args = [filter[:values]]
185
+ elsif filter[:option] == '!!'
186
+ str = "(#{column_name} IS NULL)"
187
+ args = []
188
+ else
189
+ # probably should fix this.
190
+ # somtimes we arent sending a filter option, so just default it to =
191
+ str = "(#{column_name} #{filter[:option] || '='} ANY(ARRAY[?]))"
192
+ args = [filter[:values]]
193
+ end
190
194
 
191
195
  [str, args]
192
196
  end
193
197
 
198
+ def sanitize_vector_string(search)
199
+ phrases_or = search.scan(/\+"([^"]*)"/) # e.g. +"Phrase for OR"
200
+ # remove 'or' phrases from search if any
201
+ phrases_or.each { |phrase| search.gsub!('+"' + phrase.first.to_s + '"', '') } if phrases_or.any?
202
+
203
+ phrases_to_exclude = search.scan(/-"([^"]*)"/) # e.g. -"Phrase to exclude"
204
+ # remove excluded phrases from search if any
205
+ phrases_to_exclude.each { |phrase| search.gsub!('-"' + phrase.first.to_s + '"', '') } if phrases_to_exclude.any?
206
+
207
+ phrases_and = search.scan(/"([^"]*)"/) # e.g. "Phrase for AND"
208
+ # remove 'and' phrases from search if any
209
+ phrases_and.each { |phrase| search.gsub!('"' + phrase.first.to_s + '"', '') } if phrases_and.any?
210
+
211
+ sanitized_and_terms = search.split(' ')
212
+ .reject { |term| term.include?('+') || term.include?('-') }
213
+ .map { |term| term.downcase.strip + ':*' }
214
+ .reject { |t| t.blank? }
215
+
216
+ sanitized_or_terms = search.split(' ')
217
+ .select { |term| term.include?('+') }
218
+ .map { |term| term[1, term.length].downcase + ':*' }
219
+ .reject { |t| t.blank? }
220
+
221
+ sanitized_excluded_terms = search.split(' ')
222
+ .select { |term| term.include?('-') }
223
+ .map { |term| term[1, term.length].downcase.strip + ':*' }
224
+ .reject { |t| t.blank? }
225
+
226
+ and_clause = sanitized_and_terms.join(' & ')
227
+
228
+ or_clause = sanitized_or_terms.join(' | ')
229
+
230
+ excluded_clause = sanitized_excluded_terms.map { |t| "!#{t}" }.join(' & ')
231
+
232
+ # puts '------'
233
+ # puts '------'
234
+ # puts '------'
235
+ # puts and_clause.inspect
236
+ # puts or_clause.inspect
237
+ # puts excluded_clause.inspect
238
+ # puts '------'
239
+ # puts '------'
240
+
241
+ if and_clause.present? && or_clause.empty? && excluded_clause.empty?
242
+ and_clause
243
+ elsif and_clause.empty? && or_clause.present? && excluded_clause.empty?
244
+ or_clause
245
+ elsif and_clause.empty? && or_clause.empty? && excluded_clause.present?
246
+ excluded_clause
247
+ elsif and_clause.present? && or_clause.present? && excluded_clause.empty?
248
+ "(#{and_clause}) & (#{or_clause})"
249
+ elsif and_clause.present? && or_clause.empty? && excluded_clause.present?
250
+ "(#{and_clause}) & (#{excluded_clause})"
251
+ elsif and_clause.empty? && or_clause.present? && excluded_clause.present?
252
+ "(#{or_clause}) & (#{excluded_clause})"
253
+ elsif and_clause.present? && or_clause.present? && excluded_clause.present?
254
+ "(#{and_clause}) & (#{or_clause}) & (#{excluded_clause})"
255
+ else
256
+ raise StandardError, 'Combination not available.'
257
+ end
258
+ end
259
+
260
+ def generate_vector_clause(column_name, filter)
261
+ return ['', []] if filter[:values][0].blank?
262
+
263
+ vector_string = sanitize_vector_string(filter[:values][0])
264
+
265
+ query = "(#{column_name} @@ to_tsquery('simple', ?))"
266
+ [query, [vector_string]]
267
+ end
268
+
194
269
  def generate_zip_codes_clause(column_name, filter)
195
270
  str = "(#{column_name} = ANY(#{zip_code_class.distance_query}))"
196
271
  args = zip_code_class.distance_args(filter)
@@ -200,10 +275,10 @@ module RadCoreRails
200
275
 
201
276
  def generate_array_clause(column_name, filter)
202
277
  if filter[:option] == '!='
203
- str = "(SELECT NOT(#{column_name}::text[] && ARRAY[?]))"
278
+ str = "(SELECT NOT(#{column_name}::text[] && ARRAY[?]::text[]))"
204
279
  args = [filter[:values]]
205
280
  else
206
- str = "(SELECT (#{column_name}::text[] && ARRAY[?]))"
281
+ str = "(SELECT (#{column_name}::text[] && ARRAY[?]::text[]))"
207
282
  args = [filter[:values]]
208
283
  end
209
284
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RadCoreRails
4
- VERSION = '0.7.5'
4
+ VERSION = '0.8.4'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rad_core_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 0.8.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleksandr Poltavets, James Marrs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-27 00:00:00.000000000 Z
11
+ date: 2021-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport