paginated 1.0.3 → 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 +4 -4
- data/README.md +2 -2
- data/lib/paginated/search.rb +14 -24
- data/lib/paginated/serialization.rb +7 -13
- data/lib/paginated.rb +49 -30
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60256c0f7c8df7e2fd347f31b5b713b6a878aa4554017a2aa074e05ffc9b5900
|
4
|
+
data.tar.gz: 3daaacf9ba025b0ce2b47d0990aa72b29e45037dde4c8461fb913bc21aa28f94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3a615e433b61937db50ccacea1c96857b263e7cf680cfe29c9e0feb4f678cd988a2ac34cfb24dc693884f525406262dd7bfbe60e0859ee8e6e93ae50b23f24a
|
7
|
+
data.tar.gz: 3ffafc39efb627cdfbf2bbff6f9c273421694fcc8abe6984260453cca1893ed8a65cd190740fcec7fcba0d459b4af1a0a2f7eb4374273e651f9ce4c9cb580215
|
data/README.md
CHANGED
@@ -20,7 +20,7 @@ bundle
|
|
20
20
|
|
21
21
|
Использование с помощью вызова метода `.collection` и передачи в него необходимых опций:
|
22
22
|
```
|
23
|
-
Paginated.
|
23
|
+
Paginated.collection()
|
24
24
|
```
|
25
25
|
|
26
26
|
Опции (с примерами):
|
@@ -40,7 +40,7 @@ Paginated.new.collection()
|
|
40
40
|
Например:
|
41
41
|
|
42
42
|
```
|
43
|
-
Paginated.
|
43
|
+
Paginated.collection(
|
44
44
|
model: 'User',
|
45
45
|
fields: %i[
|
46
46
|
email
|
data/lib/paginated/search.rb
CHANGED
@@ -5,9 +5,9 @@ module Search
|
|
5
5
|
private
|
6
6
|
|
7
7
|
def search
|
8
|
-
@
|
8
|
+
@search_fields&.each do |field|
|
9
9
|
# коллекция записей для дальнейшей фильтрации
|
10
|
-
|
10
|
+
list = @objects || @model.unscoped.merge(@scopes)
|
11
11
|
|
12
12
|
# оператор и значение для поиска
|
13
13
|
operator, value = search_operands(field)
|
@@ -20,7 +20,7 @@ module Search
|
|
20
20
|
# название скоупа из модели, который нужно применить
|
21
21
|
scope_name = operator.split('.')[1]
|
22
22
|
# применение скоупа
|
23
|
-
@objects =
|
23
|
+
@objects = list.send(scope_name, value)
|
24
24
|
@objects_count = @objects.count
|
25
25
|
next
|
26
26
|
end
|
@@ -32,16 +32,16 @@ module Search
|
|
32
32
|
|
33
33
|
if field.include?('.')
|
34
34
|
# нужно приджойнить таблицу
|
35
|
-
|
36
|
-
table =
|
37
|
-
|
35
|
+
join_assoc, field = field.split('.')
|
36
|
+
table = join_assoc.tableize
|
37
|
+
list = list.joins(join_assoc.to_sym)
|
38
38
|
else
|
39
39
|
table = @model.table_name
|
40
40
|
field = field.split('|')[0]
|
41
41
|
end
|
42
42
|
|
43
43
|
query = where_query(table, field, operator, value)
|
44
|
-
@objects =
|
44
|
+
@objects = list.where(query)
|
45
45
|
@objects_count = @objects.count
|
46
46
|
end
|
47
47
|
end
|
@@ -52,10 +52,10 @@ module Search
|
|
52
52
|
# WHERE query operator
|
53
53
|
operator = field.split('|').size > 1 ? field.split('|').last : '='
|
54
54
|
|
55
|
-
#
|
55
|
+
# условие для поиска ILIKE
|
56
56
|
value = "%#{value}%" if operator == 'ilike' && value.present?
|
57
57
|
|
58
|
-
#
|
58
|
+
# проверка мульти-поиска по параметру с массивом
|
59
59
|
if operator == 'multi' && !value.blank?
|
60
60
|
operator = 'IN'
|
61
61
|
value = "(#{value.join(', ')})"
|
@@ -63,13 +63,13 @@ module Search
|
|
63
63
|
|
64
64
|
# проверка диапазона (MIN/MAX)
|
65
65
|
if %w[min max].include?(operator)
|
66
|
-
range_field = field.split('.').last.split(':')[0].try { |
|
66
|
+
range_field = field.split('.').last.split(':')[0].try { |i| i.split('|')[0] }
|
67
67
|
value = @params["#{range_field}_#{operator}"]
|
68
68
|
operator = operator == 'min' ? '>=' : '<='
|
69
69
|
end
|
70
70
|
|
71
71
|
# check array operator
|
72
|
-
if operator == 'array' &&
|
72
|
+
if operator == 'array' && value.present?
|
73
73
|
operator = '='
|
74
74
|
value = "{#{value}}"
|
75
75
|
end
|
@@ -78,24 +78,14 @@ module Search
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def default_param_value(field)
|
81
|
-
|
82
|
-
|
83
|
-
# название ключа-поля без оператора (напр. ilike)
|
84
|
-
field.split('|')[0]
|
85
|
-
else
|
86
|
-
field
|
87
|
-
end
|
81
|
+
# название ключа-поля без оператора (напр. ilike)
|
82
|
+
key = field.split('|')[0]
|
88
83
|
|
89
84
|
@params[key]
|
90
85
|
end
|
91
86
|
|
92
87
|
def where_query(table, field, operator, value)
|
93
|
-
|
94
|
-
# фильтрация по дате/времени
|
95
|
-
"EXTRACT(epoch FROM #{field}) #{operator} #{value}"
|
96
|
-
else
|
97
|
-
"#{table}.#{field} #{operator} #{value}"
|
98
|
-
end
|
88
|
+
"#{table}.#{field} #{operator} #{value}"
|
99
89
|
end
|
100
90
|
|
101
91
|
def quotations_formatting(string)
|
@@ -6,20 +6,15 @@ module Serialization
|
|
6
6
|
|
7
7
|
def serialize
|
8
8
|
# коллекция записей / сущность для применения аггрегирования
|
9
|
-
|
9
|
+
list = @objects || @model.unscoped.merge(@scopes)
|
10
10
|
|
11
|
-
# применение сортировки и пагинации
|
12
|
-
@objects =
|
13
|
-
if @paginate
|
14
|
-
entity.offset(@offset).merge(sort_proc).limit(@limit)
|
15
|
-
else
|
16
|
-
entity.merge(sort_proc)
|
17
|
-
end
|
11
|
+
# применение сортировки и пагинации к коллекции записей
|
12
|
+
@objects = list.offset(@offset).merge(sort_proc).limit(@limit)
|
18
13
|
|
19
14
|
# сериализация с помощью переданных полей или сериалайзера
|
20
15
|
if @fields
|
21
16
|
serialize_with_fields
|
22
|
-
elsif @
|
17
|
+
elsif @grape_entity
|
23
18
|
serialize_with_entity
|
24
19
|
end
|
25
20
|
end
|
@@ -36,8 +31,7 @@ module Serialization
|
|
36
31
|
end
|
37
32
|
|
38
33
|
def serialize_with_entity
|
39
|
-
|
40
|
-
@objects = @objects.map { |i| entity.represent(i, current_user: @current_user).as_json }
|
34
|
+
@objects = @objects.map { |i| @grape_entity.represent(i, current_user: @current_user).as_json }
|
41
35
|
end
|
42
36
|
|
43
37
|
def sort_proc
|
@@ -72,8 +66,8 @@ module Serialization
|
|
72
66
|
end
|
73
67
|
end
|
74
68
|
|
75
|
-
def obtain_fields_values(
|
76
|
-
@fields.map { |
|
69
|
+
def obtain_fields_values(record)
|
70
|
+
@fields.map { |i| record.send(i) }
|
77
71
|
end
|
78
72
|
|
79
73
|
end
|
data/lib/paginated.rb
CHANGED
@@ -6,21 +6,16 @@ class Paginated
|
|
6
6
|
include Search
|
7
7
|
include Serialization
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@order = attrs[:order] || :id
|
18
|
-
@sort = attrs[:sort]
|
19
|
-
@model = attrs[:model].constantize
|
20
|
-
@root = @params.key?('root') ? @params['root'] : false
|
21
|
-
@paginate = @params.key?('paginate') ? @params['paginate'].to_s == 'true' : true
|
22
|
-
@objects_count = records_count(attrs[:model])
|
9
|
+
def initialize(**args)
|
10
|
+
# обработка переданных аргументов
|
11
|
+
handle_args(**args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.collection(**args)
|
15
|
+
new(**args).collection
|
16
|
+
end
|
23
17
|
|
18
|
+
def collection
|
24
19
|
if @objects_count > 0
|
25
20
|
search
|
26
21
|
serialize
|
@@ -28,32 +23,56 @@ class Paginated
|
|
28
23
|
@objects = []
|
29
24
|
end
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
@objects
|
34
|
-
else
|
35
|
-
# результат с пагинацией
|
36
|
-
{ count: @objects_count, objects: @objects }
|
37
|
-
end
|
26
|
+
# результат с пагинацией
|
27
|
+
{ count: @objects_count, objects: @objects }
|
38
28
|
end
|
39
29
|
|
40
|
-
|
30
|
+
def handle_args(**args)
|
31
|
+
# обрабатываемая Rails модель
|
32
|
+
@model = args[:model]
|
33
|
+
|
34
|
+
# параметры запроса и текущий пользователь
|
35
|
+
serialization_scope = args[:serialization_scope]
|
36
|
+
@params = serialization_scope.params.stringify_keys
|
37
|
+
@current_user = serialization_scope.current_user
|
38
|
+
|
39
|
+
# поля, по которым возможен поиск
|
40
|
+
@search_fields = args[:search]
|
41
|
+
|
42
|
+
# сериализация - через Grape Entity или список полей
|
43
|
+
@grape_entity = args[:entity]
|
44
|
+
@fields = args[:fields]
|
45
|
+
|
46
|
+
# Rails scopes для применения
|
47
|
+
@scopes = args[:scopes] || {}
|
48
|
+
|
49
|
+
# offset / limit
|
50
|
+
@offset = @params['offset'].to_i
|
51
|
+
@limit = @params['limit'] || 20
|
52
|
+
|
53
|
+
# сортировка
|
54
|
+
@order = args[:order] || :id
|
55
|
+
@sort = args[:sort]
|
56
|
+
|
57
|
+
# подсчет кол-ва записей
|
58
|
+
@objects_count = records_count
|
59
|
+
end
|
41
60
|
|
42
|
-
def records_count
|
61
|
+
def records_count
|
43
62
|
# получение кол-ва записей из кеша
|
44
|
-
cache_key = "#{
|
45
|
-
|
46
|
-
return
|
63
|
+
cache_key = "#{@model}_records_count"
|
64
|
+
cached = Rails.cache.read(cache_key)
|
65
|
+
return cached if cached
|
47
66
|
|
48
67
|
# получение кол-ва записей из запроса к БД
|
49
|
-
|
68
|
+
count = @model.merge(@scopes).count(:id)
|
50
69
|
|
51
70
|
# кеширование кол-ва записей при превышении порогового значения
|
52
|
-
if
|
53
|
-
Rails.cache.write(cache_key,
|
71
|
+
if count >= 1_000
|
72
|
+
Rails.cache.write(cache_key, count, expires_in: 30.minutes)
|
54
73
|
end
|
55
74
|
|
56
|
-
|
75
|
+
count
|
57
76
|
end
|
58
77
|
|
59
78
|
end
|
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
|
+
version: 1.0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Павел Бабин
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -81,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
requirements: []
|
84
|
-
rubygems_version: 3.
|
84
|
+
rubygems_version: 3.4.10
|
85
85
|
signing_key:
|
86
86
|
specification_version: 4
|
87
87
|
summary: Пагинация для Rails-приложений
|