grape-listing 1.3.8 → 1.4.0

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: 6ba8617bffac0ab4e4a01be9a04405601e47b623856460fac204877fc26317f7
4
- data.tar.gz: aeca947deec2736192248fef996310e5848acd3575e176c9d708c5b6623d8799
3
+ metadata.gz: 79497f0f3b194664ec9c8c5bbea0640dc346b60d6b2c9b84e6a7fbbb644da707
4
+ data.tar.gz: fc81cf3328415dc9f5a82df4ffb6fc505d1b364f7b706888f9c135d6600c4b1e
5
5
  SHA512:
6
- metadata.gz: c4cf61f5dde0b861f2cbeb372c324a02eaf9a1b71dcb6ff573f48b427abf0a10c0e232dc1851414094d0e103ee4000950d6f1a8c97553b0e9c62d01d6ee3a972
7
- data.tar.gz: cb98c65e16c43a058c1c513e223e6ff15b2a3b2a13acd538a29aba2167f232ebb363847123509efb54227ecf3abe8451bb43b6f7e34b808f676c5b7f83ca2c4d
6
+ metadata.gz: cdeb53c3deea041c1898c1ec43af53f5ef6d3732621022cc7152263ac66cfd96113569cd5f651d26ba11d7d6cab8fde2ba6760d5f677a9c707f7e37d1099d11e
7
+ data.tar.gz: 90b469c13b6c9141f9ea97d30ba79c4c76efa5b291b66c6b5a6afd276d2fbdd5b8937d70ea43521f26a0fbebe13430e69f09f918750baf4c755f7eba2d3116c8
data/lib/grape/dsl.rb CHANGED
@@ -4,13 +4,13 @@ module Grape
4
4
  module DSL
5
5
  module InsideRoute
6
6
 
7
- def listing(model:, entity:, scopes: nil, search: nil, sortable: nil, paginate: true, caching: false, preload: nil)
7
+ def listing(model:, entity:, scopes: nil, search: nil, sortable: nil, paginate: true, cache: nil, preload: nil)
8
8
  # параметры запроса API
9
9
  request_method = request.env['REQUEST_METHOD']
10
10
  request_uri = request.env['REQUEST_URI']
11
11
 
12
12
  # опции для сервиса
13
- opts = listing_opts(model, entity, scopes, search, sortable, caching, request_method, request_uri, preload)
13
+ opts = listing_opts(model, entity, scopes, search, sortable, cache, request_method, request_uri, preload)
14
14
 
15
15
  if params[:spreadsheet]
16
16
  listing_spreadsheet(**opts)
@@ -23,7 +23,7 @@ module Grape
23
23
 
24
24
  private
25
25
 
26
- def listing_opts(model, entity, scopes, search, sortable, caching, request_method, request_uri, preload)
26
+ def listing_opts(model, entity, scopes, search, sortable, cache, request_method, request_uri, preload)
27
27
  # стандартные опции
28
28
  opts = {
29
29
  model:,
@@ -34,7 +34,7 @@ module Grape
34
34
  sortable:,
35
35
  params:,
36
36
  current_user:,
37
- caching:,
37
+ cache:,
38
38
  request_method:,
39
39
  request_uri:
40
40
  }
@@ -0,0 +1,3 @@
1
+ module GrapeListing
2
+ VERSION = '1.4.0'.freeze
3
+ end
@@ -43,46 +43,11 @@ module GrapeListing
43
43
  # сортировка
44
44
  @sortable = args[:sortable]
45
45
 
46
- # подсчет кол-ва записей
47
- @objects_count = records_count
48
-
49
46
  # временная директория (для генерации файлов)
50
47
  @tempdir = args[:tempdir]
51
48
 
52
49
  # кеширование результатов обработки Grape Entity
53
- @caching = args[:caching]
54
- end
55
-
56
- def records_count
57
- # получение кол-ва записей из кеша
58
- key = count_cache_key
59
- cached = GrapeListing.cache.read(key)
60
- return cached if cached
61
-
62
- # получение кол-ва записей из запроса к БД
63
- count = @model.merge(@scopes).distinct.count(:id)
64
-
65
- # кеширование кол-ва записей при превышении порогового значения
66
- if count >= 1_000
67
- GrapeListing.cache.write(key, count, expires_in: 30.minutes)
68
- end
69
-
70
- count
71
- end
72
-
73
- def count_cache_key
74
- # необходимо убрать параметры offset и page из uri
75
- uri_path, params = @request_uri.split('?')
76
- if params
77
- params = Rack::Utils.parse_query(params).except('offset', 'page')
78
- @request_uri = params.present? ? "#{uri_path}?#{Rack::Utils.build_query(params)}" : uri_path
79
- end
80
-
81
- # пример: "GET api/v1/users?active=true"
82
- body = "#{@request_method} #{@request_uri}"
83
-
84
- enc = Digest::MD5.hexdigest(body)
85
- "listing_cached_count_#{enc}"
50
+ @cache = args[:cache]
86
51
  end
87
52
 
88
53
  end
@@ -2,12 +2,11 @@ module GrapeListing
2
2
  module Listing
3
3
 
4
4
  def listed
5
- if @objects_count > 0
6
- search
7
- list
8
- else
9
- @objects = []
10
- end
5
+ # применение фильтрации
6
+ search
7
+
8
+ # обработка записей
9
+ handle_objects_list
11
10
 
12
11
  # результат
13
12
  @objects
@@ -15,15 +14,15 @@ module GrapeListing
15
14
 
16
15
  private
17
16
 
18
- def list
17
+ def handle_objects_list
19
18
  # коллекция записей ActiveRecord для применения аггрегирования
20
19
  list = @objects || @model.preload(@preload).merge(@scopes)
21
20
 
22
21
  # применение сортировки к коллекции записей
23
22
  @objects = list.merge(sort_proc)
24
23
 
25
- # сериализация с помощью переданных полей или сериалайзера
26
- @objects = serialize(@objects)
24
+ # сериализация
25
+ @objects = represent(@objects)
27
26
  end
28
27
 
29
28
  end
@@ -2,12 +2,11 @@ module GrapeListing
2
2
  module Pagination
3
3
 
4
4
  def paginated
5
- if @objects_count > 0
6
- search
7
- paginate
8
- else
9
- @objects = []
10
- end
5
+ # применение фильтрации
6
+ search
7
+
8
+ # обработка записей
9
+ handle_paginated_list
11
10
 
12
11
  # результат с пагинацией
13
12
  { count: @objects_count, objects: @objects }
@@ -15,16 +14,52 @@ module GrapeListing
15
14
 
16
15
  private
17
16
 
18
- def paginate
17
+ def handle_paginated_list
19
18
  # коллекция записей ActiveRecord для применения аггрегирования
20
19
  list = @objects || @model.preload(@preload).merge(@scopes)
21
20
 
21
+ # подсчет кол-ва записей
22
+ @objects_count = records_count(list)
23
+
22
24
  # применение сортировки и пагинации к коллекции записей
23
25
  @objects = list.offset(@offset).merge(sort_proc).limit(@limit)
24
26
 
25
- # сериализация с помощью переданных полей или сериалайзера
26
- @objects = serialize(@objects)
27
+ # сериализация
28
+ @objects = represent(@objects)
27
29
  end
28
30
 
31
+ def records_count(list)
32
+ # получение кол-ва записей из кеша
33
+ key = count_cache_key
34
+ cached = GrapeListing.cache.read(key)
35
+ return cached if cached
36
+
37
+ # получение кол-ва записей из запроса к БД
38
+ count = list.distinct.count(:id)
39
+
40
+ # кеширование кол-ва записей при превышении порогового значения
41
+ if count >= 1_000
42
+ GrapeListing.cache.write(key, count, expires_in: 30.minutes)
43
+ end
44
+
45
+ count
46
+ end
47
+
48
+ def count_cache_key
49
+ # необходимо убрать параметры offset и page из uri
50
+ uri_path, params = @request_uri.split('?')
51
+ if params
52
+ params = Rack::Utils.parse_query(params).except('offset', 'page')
53
+ @request_uri = params.present? ? "#{uri_path}?#{Rack::Utils.build_query(params)}" : uri_path
54
+ end
55
+
56
+ # пример: "GET api/v1/users?active=true"
57
+ body = "#{@request_method} #{@request_uri}"
58
+
59
+ enc = Digest::MD5.hexdigest(body)
60
+ "listing_cached_count_#{enc}"
61
+ end
62
+
63
+
29
64
  end
30
65
  end
@@ -41,10 +41,6 @@ module GrapeListing
41
41
  query = where_query(table, field, operator, value)
42
42
  @objects = list.where(query)
43
43
  end
44
-
45
- if @objects
46
- @objects_count = @objects.distinct.count
47
- end
48
44
  end
49
45
 
50
46
  def search_operands(field)
@@ -3,6 +3,14 @@ module GrapeListing
3
3
 
4
4
  private
5
5
 
6
+ def represent(records)
7
+ if @cache.present?
8
+ cache { serialize(records) }
9
+ else
10
+ serialize(records)
11
+ end
12
+ end
13
+
6
14
  def serialize(records)
7
15
  if @fields
8
16
  serialize_with_fields(records)
@@ -11,6 +19,17 @@ module GrapeListing
11
19
  end
12
20
  end
13
21
 
22
+ def cache
23
+ # параметры кеширования
24
+ key = @cache[:key] || @model.table_name
25
+ opts = @cache.slice(:expires_in)
26
+
27
+ # непосредственное кеширование
28
+ GrapeListing.cache.fetch(key, opts) do
29
+ yield
30
+ end
31
+ end
32
+
14
33
  def serialize_with_fields(records)
15
34
  # добавление ID в список полей по умолчанию
16
35
  @fields.push(:id)
@@ -33,11 +52,7 @@ module GrapeListing
33
52
 
34
53
  # обработка результатов
35
54
  records.map do |record|
36
- if @caching
37
- caching_entity_representation(record)
38
- else
39
- @grape_entity.represent(record, @entity_opts).as_json
40
- end
55
+ @grape_entity.represent(record, @entity_opts).as_json
41
56
  end
42
57
  end
43
58
 
@@ -45,21 +60,5 @@ module GrapeListing
45
60
  @fields.map { |i| record.send(i) }
46
61
  end
47
62
 
48
- def caching_entity_representation(record)
49
- key = "#{@grape_entity}:#{record.id}"
50
-
51
- # опции кеширования
52
- opts =
53
- if @caching.is_a?(ActiveSupport::Duration)
54
- { expires_in: @caching }
55
- else
56
- {}
57
- end
58
-
59
- GrapeListing.cache.fetch(key, opts) do
60
- @grape_entity.represent(record, @entity_opts).as_json
61
- end
62
- end
63
-
64
63
  end
65
64
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-listing
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.8
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Павел Бабин
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-13 00:00:00.000000000 Z
11
+ date: 2025-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -91,6 +91,7 @@ files:
91
91
  - lib/grape/dsl.rb
92
92
  - lib/grape_listing.rb
93
93
  - lib/grape_listing/configuration.rb
94
+ - lib/grape_listing/version.rb
94
95
  - lib/grape_listing_service.rb
95
96
  - lib/listing_service/args_handling.rb
96
97
  - lib/listing_service/listing.rb
@@ -101,7 +102,7 @@ files:
101
102
  - lib/listing_service/spreadsheet.rb
102
103
  homepage:
103
104
  licenses:
104
- - MIT
105
+ - Copyright
105
106
  metadata:
106
107
  rubygems_mfa_required: 'true'
107
108
  post_install_message: