respondo 1.0.0 → 2.1.0

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.
@@ -4,20 +4,39 @@ module Respondo
4
4
  # Mixed into Rails controllers to provide render_success and render_error.
5
5
  #
6
6
  # Success helpers (2xx):
7
- # render_success, render_created, render_accepted, render_no_content,
8
- # render_partial_content, render_multi_status
7
+ # render_success, render_ok, render_created, render_accepted,
8
+ # render_non_authoritative, render_no_content, render_reset_content,
9
+ # render_partial_content, render_multi_status, render_already_reported,
10
+ # render_im_used
11
+ #
12
+ # Informational helpers (1xx):
13
+ # render_continue, render_switching_protocols, render_processing,
14
+ # render_early_hints
15
+ #
16
+ # Redirect helpers (3xx):
17
+ # render_multiple_choices, render_moved_permanently, render_found,
18
+ # render_see_other, render_not_modified, render_temporary_redirect,
19
+ # render_permanent_redirect
9
20
  #
10
21
  # Client error helpers (4xx):
11
22
  # render_bad_request, render_unauthorized, render_payment_required,
12
23
  # render_forbidden, render_not_found, render_method_not_allowed,
13
- # render_not_acceptable, render_conflict, render_gone,
14
- # render_unprocessable, render_too_many_requests, render_locked,
15
- # render_precondition_failed, render_unsupported_media_type,
16
- # render_request_timeout
24
+ # render_not_acceptable, render_proxy_auth_required, render_request_timeout,
25
+ # render_conflict, render_gone, render_length_required,
26
+ # render_precondition_failed, render_payload_too_large, render_uri_too_long,
27
+ # render_unsupported_media_type, render_range_not_satisfiable,
28
+ # render_expectation_failed, render_im_a_teapot, render_misdirected_request,
29
+ # render_unprocessable, render_locked, render_failed_dependency,
30
+ # render_too_early, render_upgrade_required, render_precondition_required,
31
+ # render_too_many_requests, render_request_header_fields_too_large,
32
+ # render_unavailable_for_legal_reasons
17
33
  #
18
34
  # Server error helpers (5xx):
19
35
  # render_server_error, render_not_implemented, render_bad_gateway,
20
- # render_service_unavailable, render_gateway_timeout
36
+ # render_service_unavailable, render_gateway_timeout,
37
+ # render_http_version_not_supported, render_variant_also_negotiates,
38
+ # render_insufficient_storage, render_loop_detected, render_not_extended,
39
+ # render_network_authentication_required
21
40
  module ControllerHelpers
22
41
 
23
42
  # =========================================================================
@@ -29,19 +48,19 @@ module Respondo
29
48
  # @param data [Object] payload — AR model, collection, Hash, Array, nil
30
49
  # @param message [String] human-readable description
31
50
  # @param meta [Hash] extra meta fields merged into the meta block
32
- # @param pagy [Pagy] optional Pagy object (pass when using Pagy backend)
33
- # @param pagination [Boolean] true = include pagination meta when available (default)
34
- # false = always suppress pagination meta
51
+ # @param pagination [Hash, nil] pagination hash built by the caller, e.g.
52
+ # { current_page: 1, per_page: 25, total_pages: 4,
53
+ # total_count: 100, next_page: 2, prev_page: nil }
54
+ # Pass nil (default) to omit pagination from meta.
35
55
  # @param status [Symbol, Integer] HTTP status (default: :ok / 200)
36
- def render_success(data: nil, message: nil, meta: {}, code: nil, pagy: nil, pagination: true, status: :ok)
37
- merged_meta = code ? meta.merge(code: code, status: status) : meta
56
+ def render_success(data: nil, message: nil, meta: {}, code: nil, pagination: nil, status: :ok)
57
+ merged_meta = code ? meta.merge(code: code, status: status) : meta
38
58
 
39
59
  payload = ResponseBuilder.new(
40
60
  success: true,
41
61
  data: data,
42
62
  message: message,
43
63
  meta: merged_meta,
44
- pagy: pagy,
45
64
  pagination: pagination,
46
65
  request: try(:request)
47
66
  ).build
@@ -67,46 +86,132 @@ module Respondo
67
86
  message: message,
68
87
  meta: merged_meta,
69
88
  errors: extracted_errors,
70
- pagination: false,
71
89
  request: try(:request)
72
90
  ).build
73
91
 
74
92
  render json: payload, status: status
75
93
  end
76
94
 
95
+ # =========================================================================
96
+ # 1xx Informational helpers
97
+ # NOTE: 1xx responses are protocol-level and don't carry a body in HTTP/1.1.
98
+ # These helpers return a JSON body for API consistency / logging purposes,
99
+ # but most HTTP clients will not receive them as normal responses.
100
+ # =========================================================================
101
+
102
+ # 100 Continue
103
+ def render_continue(message: "Continue", meta: {})
104
+ render_success(data: nil, message: message, meta: meta, code: 100, status: :continue)
105
+ end
106
+
107
+ # 101 Switching Protocols
108
+ def render_switching_protocols(message: "Switching protocols", meta: {})
109
+ render_success(data: nil, message: message, meta: meta, code: 101, status: :switching_protocols)
110
+ end
111
+
112
+ # 102 Processing (WebDAV)
113
+ def render_processing(message: "Processing", meta: {})
114
+ render_success(data: nil, message: message, meta: meta, code: 102, status: :processing)
115
+ end
116
+
117
+ # 103 Early Hints
118
+ def render_early_hints(message: "Early hints", meta: {})
119
+ render_success(data: nil, message: message, meta: meta, code: 103, status: :early_hints)
120
+ end
121
+
77
122
  # =========================================================================
78
123
  # 2xx Success helpers
79
124
  # =========================================================================
80
125
 
81
126
  # 200 OK — alias for render_success with no pagination (single record)
82
- def render_ok(data: nil, message: nil, meta: {}, pagination: true)
83
- render_success(data: data, message: message, meta: meta, pagination: pagination, code:200, status: :ok)
127
+ def render_ok(data: nil, message: nil, meta: {}, pagination: nil)
128
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 200, status: :ok)
84
129
  end
85
130
 
86
131
  # 201 Created
87
- def render_created(data: nil, message: "Created successfully", pagination: false)
88
- render_success(data: data, message: message, pagination: pagination, code:201, status: :created)
132
+ def render_created(data: nil, message: "Created successfully", meta: {}, pagination: nil)
133
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 201, status: :created)
89
134
  end
90
135
 
91
136
  # 202 Accepted — async jobs, background processing
92
- def render_accepted(data: nil, message: "Request accepted and is being processed")
93
- render_success(data: data, message: message, pagination: false, code:202, status: :accepted)
137
+ def render_accepted(data: nil, message: "Request accepted and is being processed", meta: {}, pagination: nil)
138
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 202, status: :accepted)
139
+ end
140
+
141
+ # 203 Non-Authoritative Information — response from a third-party cache/proxy
142
+ def render_non_authoritative(data: nil, message: "Non-authoritative information", meta: {}, pagination: nil)
143
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 203, status: :non_authoritative_information)
94
144
  end
95
145
 
96
146
  # 204 No Content — deletions, actions with no response body
97
147
  # Note: we still return our standard JSON structure for consistency
98
- def render_no_content(message: "Deleted successfully")
99
- render_success(data: nil, message: message, pagination: false, code:204, status: :ok)
148
+ def render_no_content(message: "Deleted successfully", meta: {}, pagination: nil)
149
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 204, status: :ok)
150
+ end
151
+
152
+ # 205 Reset Content — tell the client to reset the document view
153
+ def render_reset_content(message: "Reset content", meta: {}, pagination: nil)
154
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 205, status: :reset_content)
100
155
  end
101
156
 
102
157
  # 206 Partial Content — chunked / range responses
103
- def render_partial_content(data: nil, message: "Partial content returned", meta: {})
104
- render_success(data: data, message: message, meta: meta, pagination: false, code:206, status: :partial_content)
158
+ def render_partial_content(data: nil, message: "Partial content returned", meta: {}, pagination: nil)
159
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 206, status: :partial_content)
105
160
  end
106
161
 
107
- # 207 Multi-Status — batch operations with mixed results
108
- def render_multi_status(data: nil, message: "Multi-status response", meta: {})
109
- render_success(data: data, message: message, meta: meta, pagination: false, code:207, status: :multi_status)
162
+ # 207 Multi-Status (WebDAV) — batch operations with mixed results
163
+ def render_multi_status(data: nil, message: "Multi-status response", meta: {}, pagination: nil)
164
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 207, status: :multi_status)
165
+ end
166
+
167
+ # 208 Already Reported (WebDAV) — members already enumerated
168
+ def render_already_reported(data: nil, message: "Already reported", meta: {}, pagination: nil)
169
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 208, status: :already_reported)
170
+ end
171
+
172
+ # 226 IM Used — instance manipulations applied
173
+ def render_im_used(data: nil, message: "IM used", meta: {}, pagination: nil)
174
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 226, status: :im_used)
175
+ end
176
+
177
+ # =========================================================================
178
+ # 3xx Redirect helpers
179
+ # NOTE: Pass the target URL via meta: render_moved_permanently(meta: { redirect_url: new_url })
180
+ # =========================================================================
181
+
182
+ # 300 Multiple Choices
183
+ def render_multiple_choices(data: nil, message: "Multiple choices available", meta: {}, pagination: nil)
184
+ render_success(data: data, message: message, meta: meta, pagination: pagination, code: 300, status: :multiple_choices)
185
+ end
186
+
187
+ # 301 Moved Permanently
188
+ def render_moved_permanently(message: "Resource has moved permanently", meta: {}, pagination: nil)
189
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 301, status: :moved_permanently)
190
+ end
191
+
192
+ # 302 Found (temporary redirect)
193
+ def render_found(message: "Resource temporarily located elsewhere", meta: {}, pagination: nil)
194
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 302, status: :found)
195
+ end
196
+
197
+ # 303 See Other — redirect to another URI with GET
198
+ def render_see_other(message: "See other resource", meta: {}, pagination: nil)
199
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 303, status: :see_other)
200
+ end
201
+
202
+ # 304 Not Modified — client cache is still valid
203
+ def render_not_modified(message: "Resource not modified", meta: {}, pagination: nil)
204
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 304, status: :not_modified)
205
+ end
206
+
207
+ # 307 Temporary Redirect — repeat request with same method to new URL
208
+ def render_temporary_redirect(message: "Temporary redirect", meta: {}, pagination: nil)
209
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 307, status: :temporary_redirect)
210
+ end
211
+
212
+ # 308 Permanent Redirect — like 301 but method must not change
213
+ def render_permanent_redirect(message: "Permanent redirect", meta: {}, pagination: nil)
214
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 308, status: :permanent_redirect)
110
215
  end
111
216
 
112
217
  # =========================================================================
@@ -148,6 +253,11 @@ module Respondo
148
253
  render_error(message: message, errors: errors, meta: meta, code: 406, status: :not_acceptable)
149
254
  end
150
255
 
256
+ # 407 Proxy Authentication Required
257
+ def render_proxy_auth_required(message: "Proxy authentication required", errors: nil, meta: {})
258
+ render_error(message: message, errors: errors, meta: meta, code: 407, status: :proxy_authentication_required)
259
+ end
260
+
151
261
  # 408 Request Timeout
152
262
  def render_request_timeout(message: "Request timed out", errors: nil, meta: {})
153
263
  render_error(message: message, errors: errors, meta: meta, code: 408, status: :request_timeout)
@@ -163,16 +273,51 @@ module Respondo
163
273
  render_error(message: message, errors: errors, meta: meta, code: 410, status: :gone)
164
274
  end
165
275
 
276
+ # 411 Length Required — Content-Length header missing
277
+ def render_length_required(message: "Content-Length header required", errors: nil, meta: {})
278
+ render_error(message: message, errors: errors, meta: meta, code: 411, status: :length_required)
279
+ end
280
+
166
281
  # 412 Precondition Failed — conditional request failed
167
282
  def render_precondition_failed(message: "Precondition failed", errors: nil, meta: {})
168
283
  render_error(message: message, errors: errors, meta: meta, code: 412, status: :precondition_failed)
169
284
  end
170
285
 
286
+ # 413 Payload Too Large — request body exceeds server limit
287
+ def render_payload_too_large(message: "Payload too large", errors: nil, meta: {})
288
+ render_error(message: message, errors: errors, meta: meta, code: 413, status: :payload_too_large)
289
+ end
290
+
291
+ # 414 URI Too Long — request URI exceeds server limit
292
+ def render_uri_too_long(message: "URI too long", errors: nil, meta: {})
293
+ render_error(message: message, errors: errors, meta: meta, code: 414, status: :uri_too_long)
294
+ end
295
+
171
296
  # 415 Unsupported Media Type — wrong Content-Type header
172
297
  def render_unsupported_media_type(message: "Unsupported media type", errors: nil, meta: {})
173
298
  render_error(message: message, errors: errors, meta: meta, code: 415, status: :unsupported_media_type)
174
299
  end
175
300
 
301
+ # 416 Range Not Satisfiable — Range header cannot be fulfilled
302
+ def render_range_not_satisfiable(message: "Range not satisfiable", errors: nil, meta: {})
303
+ render_error(message: message, errors: errors, meta: meta, code: 416, status: :range_not_satisfiable)
304
+ end
305
+
306
+ # 417 Expectation Failed — Expect header cannot be met
307
+ def render_expectation_failed(message: "Expectation failed", errors: nil, meta: {})
308
+ render_error(message: message, errors: errors, meta: meta, code: 417, status: :expectation_failed)
309
+ end
310
+
311
+ # 418 I'm a Teapot — RFC 2324
312
+ def render_im_a_teapot(message: "I'm a teapot", errors: nil, meta: {})
313
+ render_error(message: message, errors: errors, meta: meta, code: 418, status: :im_a_teapot)
314
+ end
315
+
316
+ # 421 Misdirected Request — request sent to wrong server
317
+ def render_misdirected_request(message: "Misdirected request", errors: nil, meta: {})
318
+ render_error(message: message, errors: errors, meta: meta, code: 421, status: :misdirected_request)
319
+ end
320
+
176
321
  # 422 Unprocessable Entity — validation errors (most common for APIs)
177
322
  def render_unprocessable(message: "Validation failed", errors: nil, meta: {})
178
323
  render_error(message: message, errors: errors, meta: meta, code: 422, status: :unprocessable_content)
@@ -183,11 +328,41 @@ module Respondo
183
328
  render_error(message: message, errors: errors, meta: meta, code: 423, status: :locked)
184
329
  end
185
330
 
331
+ # 424 Failed Dependency (WebDAV) — previous request failed
332
+ def render_failed_dependency(message: "Failed dependency", errors: nil, meta: {})
333
+ render_error(message: message, errors: errors, meta: meta, code: 424, status: :failed_dependency)
334
+ end
335
+
336
+ # 425 Too Early — server unwilling to risk processing replayed request
337
+ def render_too_early(message: "Too early", errors: nil, meta: {})
338
+ render_error(message: message, errors: errors, meta: meta, code: 425, status: :too_early)
339
+ end
340
+
341
+ # 426 Upgrade Required — client must switch protocols
342
+ def render_upgrade_required(message: "Upgrade required", errors: nil, meta: {})
343
+ render_error(message: message, errors: errors, meta: meta, code: 426, status: :upgrade_required)
344
+ end
345
+
346
+ # 428 Precondition Required — request must be conditional
347
+ def render_precondition_required(message: "Precondition required", errors: nil, meta: {})
348
+ render_error(message: message, errors: errors, meta: meta, code: 428, status: :precondition_required)
349
+ end
350
+
186
351
  # 429 Too Many Requests — rate limiting
187
352
  def render_too_many_requests(message: "Too many requests. Please slow down.", errors: nil, meta: {})
188
353
  render_error(message: message, errors: errors, meta: meta, code: 429, status: :too_many_requests)
189
354
  end
190
355
 
356
+ # 431 Request Header Fields Too Large
357
+ def render_request_header_fields_too_large(message: "Request header fields too large", errors: nil, meta: {})
358
+ render_error(message: message, errors: errors, meta: meta, code: 431, status: :request_header_fields_too_large)
359
+ end
360
+
361
+ # 451 Unavailable for Legal Reasons — censored/DMCA etc.
362
+ def render_unavailable_for_legal_reasons(message: "Unavailable for legal reasons", errors: nil, meta: {})
363
+ render_error(message: message, errors: errors, meta: meta, code: 451, status: :unavailable_for_legal_reasons)
364
+ end
365
+
191
366
  # =========================================================================
192
367
  # 5xx Server error helpers
193
368
  # =========================================================================
@@ -217,6 +392,36 @@ module Respondo
217
392
  render_error(message: message, errors: errors, meta: meta, code: 504, status: :gateway_timeout)
218
393
  end
219
394
 
395
+ # 505 HTTP Version Not Supported
396
+ def render_http_version_not_supported(message: "HTTP version not supported", errors: nil, meta: {})
397
+ render_error(message: message, errors: errors, meta: meta, code: 505, status: :http_version_not_supported)
398
+ end
399
+
400
+ # 506 Variant Also Negotiates — server configuration error
401
+ def render_variant_also_negotiates(message: "Variant also negotiates", errors: nil, meta: {})
402
+ render_error(message: message, errors: errors, meta: meta, code: 506, status: :variant_also_negotiates)
403
+ end
404
+
405
+ # 507 Insufficient Storage (WebDAV)
406
+ def render_insufficient_storage(message: "Insufficient storage", errors: nil, meta: {})
407
+ render_error(message: message, errors: errors, meta: meta, code: 507, status: :insufficient_storage)
408
+ end
409
+
410
+ # 508 Loop Detected (WebDAV)
411
+ def render_loop_detected(message: "Loop detected", errors: nil, meta: {})
412
+ render_error(message: message, errors: errors, meta: meta, code: 508, status: :loop_detected)
413
+ end
414
+
415
+ # 510 Not Extended — further extensions needed
416
+ def render_not_extended(message: "Not extended", errors: nil, meta: {})
417
+ render_error(message: message, errors: errors, meta: meta, code: 510, status: :not_extended)
418
+ end
419
+
420
+ # 511 Network Authentication Required — must authenticate to access network
421
+ def render_network_authentication_required(message: "Network authentication required", errors: nil, meta: {})
422
+ render_error(message: message, errors: errors, meta: meta, code: 511, status: :network_authentication_required)
423
+ end
424
+
220
425
  private
221
426
 
222
427
  # Normalize errors into a plain Hash regardless of source type.
@@ -17,24 +17,24 @@ module Respondo
17
17
  # { timestamp: ISO8601 String }
18
18
  # Plus pagination keys when pagination: true and the data is a paginated collection.
19
19
  # Plus request_id when config.include_request_id is true.
20
+ # Plus pagination when a pagination hash is supplied by the caller.
20
21
  class ResponseBuilder
21
22
  # @param success [Boolean]
22
23
  # @param data [Object] anything — serialized automatically
23
24
  # @param message [String]
24
25
  # @param meta [Hash] caller-supplied extra meta (merged in)
25
26
  # @param errors [Hash] field-level errors (for 422 responses)
26
- # @param pagy [Pagy] optional Pagy object for pagination meta
27
- # @param pagination [Boolean] true = include pagination meta (default),
28
- # false = always suppress pagination meta
27
+ # @param pagination [Hash, nil] plain pagination hash supplied by the caller, e.g.
28
+ # { current_page: 1, per_page: 25, total_pages: 4,
29
+ # total_count: 100, next_page: 2, prev_page: nil }
29
30
  # @param request [Object] ActionDispatch::Request (for request_id)
30
31
  def initialize(success:, data: nil, message: nil, meta: {}, errors: nil,
31
- pagy: nil, pagination: true, request: nil)
32
+ pagination: nil, request: nil)
32
33
  @success = success
33
34
  @raw_data = data
34
35
  @message = message
35
36
  @extra_meta = meta || {}
36
37
  @errors = errors
37
- @pagy = pagy
38
38
  @pagination = pagination
39
39
  @request = request
40
40
  end
@@ -85,14 +85,10 @@ module Respondo
85
85
  # 4. Caller-supplied meta (overrides defaults)
86
86
  meta.merge!(@extra_meta)
87
87
 
88
- # 5. Pagination
89
- if @pagination
90
- pagination = @pagy ? Pagination.extract(@pagy) : Pagination.extract(@raw_data)
91
- meta[:pagination] = pagination if pagination
92
- end
88
+ # 5. Pagination — plain hash from the caller, placed last before code/status
89
+ meta[:pagination] = @pagination if @pagination.is_a?(Hash) && !@pagination.empty?
93
90
 
94
- # 6. Code and status always last
95
- # (these come from @extra_meta via render_error, so we re-pin them to the end)
91
+ # 6. Re-pin code and status to the very end
96
92
  code = meta.delete(:code)
97
93
  status = meta.delete(:status)
98
94
  meta[:code] = code if code
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Respondo
4
- VERSION = "1.0.0"
4
+ VERSION = "2.1.0"
5
5
  end
data/lib/respondo.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require_relative "respondo/version"
4
4
  require_relative "respondo/configuration"
5
5
  require_relative "respondo/serializer"
6
- require_relative "respondo/pagination"
6
+ # require_relative "respondo/pagination"
7
7
  require_relative "respondo/response_builder"
8
8
  require_relative "respondo/controller_helpers"
9
9
 
data/respondo.gemspec CHANGED
@@ -19,11 +19,20 @@ Gem::Specification.new do |spec|
19
19
  spec.license = "MIT"
20
20
  spec.required_ruby_version = ">= 2.7.0"
21
21
 
22
+ spec.metadata = {
23
+ "homepage_uri" => spec.homepage,
24
+ "source_code_uri" => spec.homepage,
25
+ "changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md",
26
+ "bug_tracker_uri" => "#{spec.homepage}/auditron/issues",
27
+ "rubygems_mfa_required" => "true"
28
+ }
29
+
22
30
  spec.files = Dir["lib/**/*.rb", "README.md", "LICENSE.txt", "CHANGELOG.md", "respondo.gemspec"]
23
31
  spec.require_paths = ["lib"]
24
32
 
25
- spec.add_development_dependency "rspec", "~> 3.12"
26
- spec.add_development_dependency "rake", "~> 13.0"
27
- spec.add_development_dependency "activesupport","~> 7.0"
28
- spec.add_development_dependency 'simplecov', '~> 0.22'
33
+ spec.add_development_dependency "railties", "~> 8.1.3"
34
+ spec.add_development_dependency "rspec", "~> 3.12"
35
+ spec.add_development_dependency "rake", "~> 13.0"
36
+ spec.add_development_dependency "activesupport", "~> 8.1.3"
37
+ spec.add_development_dependency 'simplecov', "~> 0.22"
29
38
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: respondo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - shailendra Kumar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-03 00:00:00.000000000 Z
11
+ date: 2026-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 8.1.3
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 8.1.3
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rspec
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +58,14 @@ dependencies:
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '7.0'
61
+ version: 8.1.3
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '7.0'
68
+ version: 8.1.3
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: simplecov
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,10 +94,10 @@ files:
80
94
  - CHANGELOG.md
81
95
  - LICENSE.txt
82
96
  - README.md
97
+ - lib/generators/respondo/install/install_generator.rb
83
98
  - lib/respondo.rb
84
99
  - lib/respondo/configuration.rb
85
100
  - lib/respondo/controller_helpers.rb
86
- - lib/respondo/pagination.rb
87
101
  - lib/respondo/railtie.rb
88
102
  - lib/respondo/response_builder.rb
89
103
  - lib/respondo/serializer.rb
@@ -92,7 +106,12 @@ files:
92
106
  homepage: https://github.com/spatelpatidar/respondo
93
107
  licenses:
94
108
  - MIT
95
- metadata: {}
109
+ metadata:
110
+ homepage_uri: https://github.com/spatelpatidar/respondo
111
+ source_code_uri: https://github.com/spatelpatidar/respondo
112
+ changelog_uri: https://github.com/spatelpatidar/respondo/blob/main/CHANGELOG.md
113
+ bug_tracker_uri: https://github.com/spatelpatidar/respondo/auditron/issues
114
+ rubygems_mfa_required: 'true'
96
115
  post_install_message:
97
116
  rdoc_options: []
98
117
  require_paths:
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Respondo
4
- # Extracts pagination metadata from Kaminari or Pagy collection objects.
5
- #
6
- # Returned hash shape (always the same regardless of pagination library):
7
- # {
8
- # current_page: Integer,
9
- # per_page: Integer,
10
- # total_pages: Integer,
11
- # total_count: Integer,
12
- # next_page: Integer | nil,
13
- # prev_page: Integer | nil
14
- # }
15
- module Pagination
16
- module_function
17
-
18
- # @param collection [Object] any object — returns nil if not a paginated collection
19
- # @return [Hash, nil]
20
- def extract(collection)
21
- return nil if collection.nil?
22
-
23
- if pagy?(collection)
24
- from_pagy(collection)
25
- elsif kaminari?(collection)
26
- from_kaminari(collection)
27
- elsif will_paginate?(collection)
28
- from_will_paginate(collection)
29
- else
30
- nil
31
- end
32
- end
33
-
34
- private
35
-
36
- module_function
37
-
38
- # ----- Pagy ---------------------------------------------------------------
39
- # Pagy stores metadata on a separate Pagy object, not the collection itself.
40
- # We support both: passing the Pagy object directly, or a collection that
41
- # has been decorated with pagy metadata via pagy_metadata.
42
- def pagy?(object)
43
- defined?(Pagy) && object.is_a?(Pagy)
44
- end
45
-
46
- def from_pagy(pagy)
47
- {
48
- current_page: pagy.page,
49
- per_page: pagy.items,
50
- total_pages: pagy.pages,
51
- total_count: pagy.count,
52
- next_page: pagy.next,
53
- prev_page: pagy.prev
54
- }
55
- end
56
-
57
- # ----- Kaminari -----------------------------------------------------------
58
- def kaminari?(object)
59
- object.respond_to?(:current_page) &&
60
- object.respond_to?(:total_pages) &&
61
- object.respond_to?(:limit_value)
62
- end
63
-
64
- def from_kaminari(collection)
65
- {
66
- current_page: collection.current_page,
67
- per_page: collection.limit_value,
68
- total_pages: collection.total_pages,
69
- total_count: collection.total_count,
70
- next_page: collection.next_page,
71
- prev_page: collection.prev_page
72
- }
73
- end
74
-
75
- # ----- WillPaginate -------------------------------------------------------
76
- def will_paginate?(object)
77
- object.respond_to?(:current_page) &&
78
- object.respond_to?(:total_pages) &&
79
- object.respond_to?(:per_page) &&
80
- !object.respond_to?(:limit_value) # distinguishes from Kaminari
81
- end
82
-
83
- def from_will_paginate(collection)
84
- {
85
- current_page: collection.current_page,
86
- per_page: collection.per_page,
87
- total_pages: collection.total_pages,
88
- total_count: collection.total_entries,
89
- next_page: collection.next_page,
90
- prev_page: collection.previous_page
91
- }
92
- end
93
- end
94
- end