paginated 1.0.4 → 1.0.4.1

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: 8b38840cf61263ac1ee6c8a3a239db1bd1e4e6d852e9ce25919286f2a35b6767
4
- data.tar.gz: 7160149eb3a72516e113827d8c0ac756322f61160d2b95480f55b91e824daae9
3
+ metadata.gz: 60256c0f7c8df7e2fd347f31b5b713b6a878aa4554017a2aa074e05ffc9b5900
4
+ data.tar.gz: 3daaacf9ba025b0ce2b47d0990aa72b29e45037dde4c8461fb913bc21aa28f94
5
5
  SHA512:
6
- metadata.gz: e8a1f43f03ea4e249ff01d03964a9c7d4b9eab658683d3a570b1698800a2bc83edb329faff24ea284552bfbb3190e6d1884b1d5be17fa2956699c845965c5414
7
- data.tar.gz: 2ea45ab22ed18d3d807e2a150c3da237bdc3de2bdc48033a0250acb7593a864a0178ef80e43774de63fa7ae016747757305b033d155fd7fc948c078adc24a547
6
+ metadata.gz: d3a615e433b61937db50ccacea1c96857b263e7cf680cfe29c9e0feb4f678cd988a2ac34cfb24dc693884f525406262dd7bfbe60e0859ee8e6e93ae50b23f24a
7
+ data.tar.gz: 3ffafc39efb627cdfbf2bbff6f9c273421694fcc8abe6984260453cca1893ed8a65cd190740fcec7fcba0d459b4af1a0a2f7eb4374273e651f9ce4c9cb580215
@@ -4,98 +4,96 @@ module Search
4
4
 
5
5
  private
6
6
 
7
- class_methods do
8
- def search
9
- @search_fields&.each do |field|
10
- # коллекция записей для дальнейшей фильтрации
11
- list = @objects || @model.unscoped.merge(@scopes)
12
-
13
- # оператор и значение для поиска
14
- operator, value = search_operands(field)
15
-
16
- # пропускаем, если параметр для поиска не передан
17
- next if value.blank? || value == 'null'
18
-
19
- # кастомный поиск
20
- if operator.include?('custom_search') && value.present?
21
- # название скоупа из модели, который нужно применить
22
- scope_name = operator.split('.')[1]
23
- # применение скоупа
24
- @objects = list.send(scope_name, value)
25
- @objects_count = @objects.count
26
- next
27
- end
28
-
29
- # форматирование кавычек
30
- if operator != 'IN' && !@model.defined_enums.key?(field)
31
- value = quotations_formatting(value)
32
- end
33
-
34
- if field.include?('.')
35
- # нужно приджойнить таблицу
36
- join_assoc, field = field.split('.')
37
- table = join_assoc.tableize
38
- list = list.joins(join_assoc.to_sym)
39
- else
40
- table = @model.table_name
41
- field = field.split('|')[0]
42
- end
43
-
44
- query = where_query(table, field, operator, value)
45
- @objects = list.where(query)
7
+ def search
8
+ @search_fields&.each do |field|
9
+ # коллекция записей для дальнейшей фильтрации
10
+ list = @objects || @model.unscoped.merge(@scopes)
11
+
12
+ # оператор и значение для поиска
13
+ operator, value = search_operands(field)
14
+
15
+ # пропускаем, если параметр для поиска не передан
16
+ next if value.blank? || value == 'null'
17
+
18
+ # кастомный поиск
19
+ if operator.include?('custom_search') && value.present?
20
+ # название скоупа из модели, который нужно применить
21
+ scope_name = operator.split('.')[1]
22
+ # применение скоупа
23
+ @objects = list.send(scope_name, value)
46
24
  @objects_count = @objects.count
25
+ next
47
26
  end
48
- end
49
27
 
50
- def search_operands(field)
51
- value = default_param_value(field)
28
+ # форматирование кавычек
29
+ if operator != 'IN' && !@model.defined_enums.key?(field)
30
+ value = quotations_formatting(value)
31
+ end
52
32
 
53
- # WHERE query operator
54
- operator = field.split('|').size > 1 ? field.split('|').last : '='
33
+ if field.include?('.')
34
+ # нужно приджойнить таблицу
35
+ join_assoc, field = field.split('.')
36
+ table = join_assoc.tableize
37
+ list = list.joins(join_assoc.to_sym)
38
+ else
39
+ table = @model.table_name
40
+ field = field.split('|')[0]
41
+ end
55
42
 
56
- # условие для поиска ILIKE
57
- value = "%#{value}%" if operator == 'ilike' && value.present?
43
+ query = where_query(table, field, operator, value)
44
+ @objects = list.where(query)
45
+ @objects_count = @objects.count
46
+ end
47
+ end
58
48
 
59
- # проверка мульти-поиска по параметру с массивом
60
- if operator == 'multi' && !value.blank?
61
- operator = 'IN'
62
- value = "(#{value.join(', ')})"
63
- end
49
+ def search_operands(field)
50
+ value = default_param_value(field)
64
51
 
65
- # проверка диапазона (MIN/MAX)
66
- if %w[min max].include?(operator)
67
- range_field = field.split('.').last.split(':')[0].try { |i| i.split('|')[0] }
68
- value = @params["#{range_field}_#{operator}"]
69
- operator = operator == 'min' ? '>=' : '<='
70
- end
52
+ # WHERE query operator
53
+ operator = field.split('|').size > 1 ? field.split('|').last : '='
71
54
 
72
- # check array operator
73
- if operator == 'array' && value.present?
74
- operator = '='
75
- value = "{#{value}}"
76
- end
55
+ # условие для поиска ILIKE
56
+ value = "%#{value}%" if operator == 'ilike' && value.present?
77
57
 
78
- [operator, value]
58
+ # проверка мульти-поиска по параметру с массивом
59
+ if operator == 'multi' && !value.blank?
60
+ operator = 'IN'
61
+ value = "(#{value.join(', ')})"
79
62
  end
80
63
 
81
- def default_param_value(field)
82
- # название ключа-поля без оператора (напр. ilike)
83
- key = field.split('|')[0]
84
-
85
- @params[key]
64
+ # проверка диапазона (MIN/MAX)
65
+ if %w[min max].include?(operator)
66
+ range_field = field.split('.').last.split(':')[0].try { |i| i.split('|')[0] }
67
+ value = @params["#{range_field}_#{operator}"]
68
+ operator = operator == 'min' ? '>=' : '<='
86
69
  end
87
70
 
88
- def where_query(table, field, operator, value)
89
- "#{table}.#{field} #{operator} #{value}"
71
+ # check array operator
72
+ if operator == 'array' && value.present?
73
+ operator = '='
74
+ value = "{#{value}}"
90
75
  end
91
76
 
92
- def quotations_formatting(string)
93
- # удаление одинарных кавычек (напр. внутри строки)
94
- value = string.to_s.gsub(/'/, '')
77
+ [operator, value]
78
+ end
95
79
 
96
- # добавление одинарных кавычек вокруг строки
97
- "'#{value}'"
98
- end
80
+ def default_param_value(field)
81
+ # название ключа-поля без оператора (напр. ilike)
82
+ key = field.split('|')[0]
83
+
84
+ @params[key]
85
+ end
86
+
87
+ def where_query(table, field, operator, value)
88
+ "#{table}.#{field} #{operator} #{value}"
89
+ end
90
+
91
+ def quotations_formatting(string)
92
+ # удаление одинарных кавычек (напр. внутри строки)
93
+ value = string.to_s.gsub(/'/, '')
94
+
95
+ # добавление одинарных кавычек вокруг строки
96
+ "'#{value}'"
99
97
  end
100
98
 
101
99
  end
@@ -4,72 +4,70 @@ module Serialization
4
4
 
5
5
  private
6
6
 
7
- class_methods do
8
- def serialize
9
- # коллекция записей / сущность для применения аггрегирования
10
- list = @objects || @model.unscoped.merge(@scopes)
11
-
12
- # применение сортировки и пагинации к коллекции записей
13
- @objects = list.offset(@offset).merge(sort_proc).limit(@limit)
14
-
15
- # сериализация с помощью переданных полей или сериалайзера
16
- if @fields
17
- serialize_with_fields
18
- elsif @grape_entity
19
- serialize_with_entity
20
- end
7
+ def serialize
8
+ # коллекция записей / сущность для применения аггрегирования
9
+ list = @objects || @model.unscoped.merge(@scopes)
10
+
11
+ # применение сортировки и пагинации к коллекции записей
12
+ @objects = list.offset(@offset).merge(sort_proc).limit(@limit)
13
+
14
+ # сериализация с помощью переданных полей или сериалайзера
15
+ if @fields
16
+ serialize_with_fields
17
+ elsif @grape_entity
18
+ serialize_with_entity
21
19
  end
20
+ end
22
21
 
23
- def serialize_with_fields
24
- # добавление ID в список полей по умолчанию
25
- @fields.push(:id)
22
+ def serialize_with_fields
23
+ # добавление ID в список полей по умолчанию
24
+ @fields.push(:id)
26
25
 
27
- # список массивов значений
28
- @objects = @objects.map { |i| obtain_fields_values(i) }
26
+ # список массивов значений
27
+ @objects = @objects.map { |i| obtain_fields_values(i) }
29
28
 
30
- # трансформация массивов значений в объекты (ключ-значение)
31
- @objects = @objects.map { |i| @fields.zip(i).to_h }
32
- end
29
+ # трансформация массивов значений в объекты (ключ-значение)
30
+ @objects = @objects.map { |i| @fields.zip(i).to_h }
31
+ end
33
32
 
34
- def serialize_with_entity
35
- @objects = @objects.map { |i| @grape_entity.represent(i, current_user: @current_user).as_json }
36
- end
33
+ def serialize_with_entity
34
+ @objects = @objects.map { |i| @grape_entity.represent(i, current_user: @current_user).as_json }
35
+ end
37
36
 
38
- def sort_proc
39
- # сортировка не задана явно, не передан параметр
40
- # или значение переданного параметра не совпадает с ожидаемым
41
- if @sort.blank? || @sort.map { |i| i.split('|')[0] }.exclude?(@params[:sort])
42
- field = @order
43
- return proc { order("#{field} DESC") }
44
- end
37
+ def sort_proc
38
+ # сортировка не задана явно, не передан параметр
39
+ # или значение переданного параметра не совпадает с ожидаемым
40
+ if @sort.blank? || @sort.map { |i| i.split('|')[0] }.exclude?(@params[:sort])
41
+ field = @order
42
+ return proc { order("#{field} DESC") }
43
+ end
45
44
 
46
- @sort.each do |sort_option|
47
- sort, field = sort_option.split('|')
45
+ @sort.each do |sort_option|
46
+ sort, field = sort_option.split('|')
48
47
 
49
- # пропускаем, если поле для сортировки не совпадает с переданным параметром
50
- next if @params[:sort] != sort
48
+ # пропускаем, если поле для сортировки не совпадает с переданным параметром
49
+ next if @params[:sort] != sort
51
50
 
52
- # если поле для сортировки совпадает с ключом переданного параметра
53
- field = sort if field.blank?
51
+ # если поле для сортировки совпадает с ключом переданного параметра
52
+ field = sort if field.blank?
54
53
 
55
- sort_order = "#{@params[:sort_order]} NULLS LAST"
54
+ sort_order = "#{@params[:sort_order]} NULLS LAST"
56
55
 
57
- order_proc =
58
- if field.split('.').count > 1
59
- # сортировка по связанной таблице
60
- relation, column = field.split('.')
61
- proc { eager_load(relation).order("#{relation.tableize}.#{column} #{sort_order}") }
62
- else
63
- proc { order("#{field} #{sort_order}") }
64
- end
56
+ order_proc =
57
+ if field.split('.').count > 1
58
+ # сортировка по связанной таблице
59
+ relation, column = field.split('.')
60
+ proc { eager_load(relation).order("#{relation.tableize}.#{column} #{sort_order}") }
61
+ else
62
+ proc { order("#{field} #{sort_order}") }
63
+ end
65
64
 
66
- return order_proc
67
- end
65
+ return order_proc
68
66
  end
67
+ end
69
68
 
70
- def obtain_fields_values(record)
71
- @fields.map { |i| record.send(i) }
72
- end
69
+ def obtain_fields_values(record)
70
+ @fields.map { |i| record.send(i) }
73
71
  end
74
72
 
75
73
  end
data/lib/paginated.rb CHANGED
@@ -6,13 +6,16 @@ class Paginated
6
6
  include Search
7
7
  include Serialization
8
8
 
9
- def self.collection(**args)
9
+ def initialize(**args)
10
10
  # обработка переданных аргументов
11
11
  handle_args(**args)
12
+ end
12
13
 
13
- # подсчет кол-ва записей
14
- @objects_count = records_count
14
+ def self.collection(**args)
15
+ new(**args).collection
16
+ end
15
17
 
18
+ def collection
16
19
  if @objects_count > 0
17
20
  search
18
21
  serialize
@@ -24,7 +27,7 @@ class Paginated
24
27
  { count: @objects_count, objects: @objects }
25
28
  end
26
29
 
27
- def self.handle_args(**args)
30
+ def handle_args(**args)
28
31
  # обрабатываемая Rails модель
29
32
  @model = args[:model]
30
33
 
@@ -50,9 +53,12 @@ class Paginated
50
53
  # сортировка
51
54
  @order = args[:order] || :id
52
55
  @sort = args[:sort]
56
+
57
+ # подсчет кол-ва записей
58
+ @objects_count = records_count
53
59
  end
54
60
 
55
- def self.records_count
61
+ def records_count
56
62
  # получение кол-ва записей из кеша
57
63
  cache_key = "#{@model}_records_count"
58
64
  cached = Rails.cache.read(cache_key)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paginated
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Павел Бабин