noiseless 0.7.1 → 0.7.2
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3a2305879802aa874c213e1a5a87707ec7222af979d21834f21f4fd2c994cb48
|
|
4
|
+
data.tar.gz: 065cf12ecb097ac17ee1e33d99d5df0ccb79ca4ea6713640f82f6bcac2fad51a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc5302df3e73a9a413e1a7382db1334e11dd28ee2564bb5ae9e0f5d6a2d62f7b241584463678ef6f0db6112740c70d5687fdc425903979056c9d61ff10140bc6
|
|
7
|
+
data.tar.gz: baba1a26426413fef74f6f900d3146aa9c7bcda385030dd3b722e8277c5dc5b8a25bb79adbf6dc9d0c695e4d3b43e4353e4fe99e3bffb7ec5fc5a0d18ff566cf
|
|
@@ -169,11 +169,11 @@ module Noiseless
|
|
|
169
169
|
when AST::MultiMatch
|
|
170
170
|
apply_multi_match(scope, node, model)
|
|
171
171
|
when AST::Wildcard
|
|
172
|
-
apply_wildcard(scope, node)
|
|
172
|
+
apply_wildcard(scope, node, model)
|
|
173
173
|
when AST::Range
|
|
174
|
-
apply_range(scope, node)
|
|
174
|
+
apply_range(scope, node, model)
|
|
175
175
|
when AST::Prefix
|
|
176
|
-
apply_prefix(scope, node)
|
|
176
|
+
apply_prefix(scope, node, model)
|
|
177
177
|
else
|
|
178
178
|
scope
|
|
179
179
|
end
|
|
@@ -190,11 +190,12 @@ module Noiseless
|
|
|
190
190
|
# cannot be satisfied here; fail closed rather than matching everything.
|
|
191
191
|
return scope.none unless column?(model, field)
|
|
192
192
|
|
|
193
|
-
# Use pg_trgm similarity for fuzzy matching
|
|
193
|
+
# Use pg_trgm similarity for fuzzy matching, accent-insensitive when
|
|
194
|
+
# the unaccent extension is present.
|
|
194
195
|
if trgm_available? && text_column?(model, field)
|
|
195
196
|
scope.where(
|
|
196
|
-
"
|
|
197
|
-
"
|
|
197
|
+
"#{fuzzy_column(field)} % #{fuzzy_param} OR " \
|
|
198
|
+
"#{fuzzy_column(field)} ILIKE #{fuzzy_param}",
|
|
198
199
|
value,
|
|
199
200
|
"%#{sanitize_like(value)}%"
|
|
200
201
|
)
|
|
@@ -213,8 +214,8 @@ module Noiseless
|
|
|
213
214
|
|
|
214
215
|
conditions = fields.map do |field|
|
|
215
216
|
if trgm_available? && text_column?(model, field)
|
|
216
|
-
"(
|
|
217
|
-
"
|
|
217
|
+
"(#{fuzzy_column(field)} % #{fuzzy_param} OR " \
|
|
218
|
+
"#{fuzzy_column(field)} ILIKE #{fuzzy_param})"
|
|
218
219
|
else
|
|
219
220
|
"#{quoted_column(field)} ILIKE ?"
|
|
220
221
|
end
|
|
@@ -231,15 +232,19 @@ module Noiseless
|
|
|
231
232
|
scope.where(conditions.join(" OR "), *params)
|
|
232
233
|
end
|
|
233
234
|
|
|
234
|
-
def apply_wildcard(scope, node)
|
|
235
|
+
def apply_wildcard(scope, node, model = nil)
|
|
235
236
|
field = node.field.to_s
|
|
237
|
+
return scope.none if model && !column?(model, field)
|
|
238
|
+
|
|
236
239
|
# Convert OpenSearch wildcards to SQL: * -> %, ? -> _
|
|
237
240
|
pattern = node.value.to_s.tr("*", "%").tr("?", "_")
|
|
238
241
|
|
|
239
242
|
scope.where("#{quoted_column(field)} ILIKE ?", pattern)
|
|
240
243
|
end
|
|
241
244
|
|
|
242
|
-
def apply_range(scope, node)
|
|
245
|
+
def apply_range(scope, node, model = nil)
|
|
246
|
+
return scope.none if model && !column?(model, node.field.to_s)
|
|
247
|
+
|
|
243
248
|
field = quoted_column(node.field.to_s)
|
|
244
249
|
|
|
245
250
|
scope = scope.where("#{field} >= ?", node.gte) if node.gte
|
|
@@ -250,7 +255,9 @@ module Noiseless
|
|
|
250
255
|
scope
|
|
251
256
|
end
|
|
252
257
|
|
|
253
|
-
def apply_prefix(scope, node)
|
|
258
|
+
def apply_prefix(scope, node, model = nil)
|
|
259
|
+
return scope.none if model && !column?(model, node.field.to_s)
|
|
260
|
+
|
|
254
261
|
scope.where("#{quoted_column(node.field.to_s)} ILIKE ?", "#{sanitize_like(node.value)}%")
|
|
255
262
|
end
|
|
256
263
|
|
|
@@ -266,6 +273,8 @@ module Noiseless
|
|
|
266
273
|
# A filter on a mapping-only field cannot be enforced;
|
|
267
274
|
# silently dropping it would broaden results, so fail closed.
|
|
268
275
|
scope.none
|
|
276
|
+
elsif model && array_column?(model, node.field.to_s)
|
|
277
|
+
apply_array_filter(scope, node.field.to_s, value, model)
|
|
269
278
|
else
|
|
270
279
|
scope.where(node.field => value)
|
|
271
280
|
end
|
|
@@ -274,6 +283,13 @@ module Noiseless
|
|
|
274
283
|
scope
|
|
275
284
|
end
|
|
276
285
|
|
|
286
|
+
def apply_array_filter(scope, field, value, model)
|
|
287
|
+
cast = "#{model.columns_hash[field].sql_type.sub(/\[\]\z/, '')}[]"
|
|
288
|
+
operator = value.is_a?(Array) ? "&&" : "@>"
|
|
289
|
+
|
|
290
|
+
scope.where("#{quoted_column(field)} #{operator} ARRAY[?]::#{cast}", value)
|
|
291
|
+
end
|
|
292
|
+
|
|
277
293
|
def apply_geo_filter(scope, node)
|
|
278
294
|
# Requires PostGIS
|
|
279
295
|
geo_config = node.value[:geo_distance]
|
|
@@ -297,17 +313,20 @@ module Noiseless
|
|
|
297
313
|
end
|
|
298
314
|
|
|
299
315
|
def apply_sorting(scope, sort_nodes, model = nil)
|
|
300
|
-
|
|
301
|
-
|
|
316
|
+
sorted_fields = []
|
|
302
317
|
order_clauses = sort_nodes.filter_map do |node|
|
|
303
318
|
field = node.field.to_s
|
|
304
319
|
# Sorting on a mapping-only field is cosmetic — drop it instead of
|
|
305
320
|
# erroring the whole query.
|
|
306
321
|
next if model && !column?(model, field)
|
|
307
322
|
|
|
323
|
+
sorted_fields << field
|
|
308
324
|
direction = node.direction.to_s.upcase == "DESC" ? "DESC" : "ASC"
|
|
309
325
|
"#{quoted_column(field)} #{direction}"
|
|
310
326
|
end
|
|
327
|
+
|
|
328
|
+
primary_key = model.respond_to?(:primary_key) ? model.primary_key : nil
|
|
329
|
+
order_clauses << "#{quoted_column(primary_key)} ASC" if primary_key && !sorted_fields.include?(primary_key.to_s)
|
|
311
330
|
return scope if order_clauses.empty?
|
|
312
331
|
|
|
313
332
|
scope.order(Arel.sql(order_clauses.join(", ")))
|
|
@@ -415,6 +434,18 @@ module Noiseless
|
|
|
415
434
|
column && %i[string text citext].include?(column.type) && !column.array
|
|
416
435
|
end
|
|
417
436
|
|
|
437
|
+
def array_column?(model, field)
|
|
438
|
+
model.columns_hash[field.to_s]&.array
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def fuzzy_column(field)
|
|
442
|
+
unaccent_available? ? "unaccent(#{quoted_column(field)})" : quoted_column(field)
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def fuzzy_param
|
|
446
|
+
unaccent_available? ? "unaccent(?)" : "?"
|
|
447
|
+
end
|
|
448
|
+
|
|
418
449
|
def quoted_column(field)
|
|
419
450
|
ActiveRecord::Base.connection.quote_column_name(field)
|
|
420
451
|
end
|
data/lib/noiseless/version.rb
CHANGED