paginated 1.0.4 → 1.0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b38840cf61263ac1ee6c8a3a239db1bd1e4e6d852e9ce25919286f2a35b6767
4
- data.tar.gz: 7160149eb3a72516e113827d8c0ac756322f61160d2b95480f55b91e824daae9
3
+ metadata.gz: 49f9695ec19cbd557cbd15ec981e775e3572371a428e0a6b0ae2abc6803e4201
4
+ data.tar.gz: 2f59100f090ccac1c1696d925273f65a2e55de67f5a68cad6f3911700c31f8a0
5
5
  SHA512:
6
- metadata.gz: e8a1f43f03ea4e249ff01d03964a9c7d4b9eab658683d3a570b1698800a2bc83edb329faff24ea284552bfbb3190e6d1884b1d5be17fa2956699c845965c5414
7
- data.tar.gz: 2ea45ab22ed18d3d807e2a150c3da237bdc3de2bdc48033a0250acb7593a864a0178ef80e43774de63fa7ae016747757305b033d155fd7fc948c078adc24a547
6
+ metadata.gz: 5b0d8b686bbf1ace12b48c1aa7059f6f55b82a2281aa36454eccadefb2814b04977071911f2b11482a79c678537bed0c40ccd18e23f3736e0331cda9b1cd13d4
7
+ data.tar.gz: d6e047296b4a80fbdbe756b1f39e64c8ff505a5993d4cc4be713dc0b2b01d39a6ed97851678306f962b7cf06a66b29592a069b377289c2737de54d5f7136f6ef
data/README.md CHANGED
@@ -49,7 +49,7 @@ Paginated.collection(
49
49
  search: %w[
50
50
  email
51
51
  name|ilike
52
- role|custom_search.for_role
52
+ role|custom.for_role
53
53
  ],
54
54
  params:,
55
55
  order: :name,
@@ -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') && 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,14 +1,14 @@
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.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Павел Бабин
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-07 00:00:00.000000000 Z
11
+ date: 2024-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails