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 +4 -4
- data/lib/rad_core_rails/query_generator.rb +129 -54
- data/lib/rad_core_rails/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82f95dfd6c84c8aa3594f89b742563c9d2d07c0637ae18432acabd352c6ff088
|
4
|
+
data.tar.gz: bf435325dc6b733c186167a643c07330d10da47fa165328b14465109986af93e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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(
|
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
|
-
|
34
|
-
end
|
35
|
-
filters.map do |
|
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(
|
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
|
-
|
61
|
-
|
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!('-"' +
|
69
|
+
phrases_to_exclude.each { |phrase| search.gsub!('-"' + phrase.first.to_s + '"', '') }
|
66
70
|
end
|
67
71
|
|
68
|
-
|
69
|
-
if
|
70
|
-
|
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
|
-
|
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 ') + '))',
|
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 ') + '))',
|
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
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
|
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.
|
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-
|
11
|
+
date: 2021-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|