respondo 2.1.0 → 2.1.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: fb5118a5648863ec54d68805d897485f40da5b81b9b628b9b9a08d6ee2f735d7
4
- data.tar.gz: 4282b491b0bd587ba668e7accaf19f6dfb879cc61261d64d744de69c803ae8a0
3
+ metadata.gz: fbe7751852587a50eb66e9d18128db0f0b98295f6e309ea1db812d2c6802827e
4
+ data.tar.gz: d59797929ccbf67f507eba232a36c04f5642318b1f3992aa0251f3949b4ed284
5
5
  SHA512:
6
- metadata.gz: 4ae4daae47ef9c2c66388fc6d8f3a915b66439208fafa25b7046234813229704de0e53863921f2b4e2100817218b2a315ef40a564c5f672a9848194e55814906
7
- data.tar.gz: 86a9ecb6864c1bba75dc4d47941bd0f80c837f4dbc72ed424526e1dad3f05ead92b738a417a239f3fb160e7043fc465418fe6670948be147399ea90ee3ce85d8
6
+ metadata.gz: d3d210ee9413164b2d0b80b4c84e8f238ffac624145704dbabfb4a09242d655460e18ecd0591cd010a43a5a9c37d1b0a1ad6086ac0ab8f0a7e36536f0d6b16c3
7
+ data.tar.gz: 8683372f8e107d696b62d6f5e69e9f693638ce3dc50f21775d54820781c987fae14e924bce00c126b83747ce8ef14857652582a7a1e0d1c881c1536c7c4bbfe5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,63 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.1.1] — Bug Fix
4
+
5
+ ### Fixed
6
+
7
+ #### `render_no_content` — status mismatch corrected
8
+ Previously `render_no_content` was sending `status: :ok` (200) while setting
9
+ `code: 204` in the meta block. This meant the HTTP response status was 200
10
+ but the meta claimed 204 — inconsistent and misleading to clients.
11
+
12
+ **Before (buggy):**
13
+ ```ruby
14
+ def render_no_content(message: "Deleted successfully", meta: {}, pagination: nil)
15
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 204, status: :ok)
16
+ # ^^^^^^^^^^
17
+ # wrong — sends 200
18
+ end
19
+ ```
20
+
21
+ **After (fixed):**
22
+ ```ruby
23
+ def render_no_content(message: "Deleted successfully", meta: {}, pagination: nil)
24
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 204, status: :no_content)
25
+ # ^^^^^^^^^^^^^^^^^^
26
+ # correct — sends 204
27
+ end
28
+ ```
29
+
30
+ **Why body is kept:** HTTP spec discourages a body on 204 but does not
31
+ strictly forbid it. Respondo keeps the JSON body so FE clients can display
32
+ the `message` field on delete confirmations. Rails and all major HTTP clients
33
+ (Axios, Fetch, OkHttp) handle this correctly.
34
+
35
+ **Migration:** No changes needed — method signature is identical. If you were
36
+ relying on the incorrect 200 status in tests, update your assertions to
37
+ expect 204.
38
+
39
+ ### Changed
40
+
41
+ #### `respondo.gemspec` — corrected `bug_tracker_uri`
42
+ A stray `auditron/` path segment was present in the `bug_tracker_uri` metadata
43
+ field, producing a broken link on RubyGems.
44
+
45
+ **Before:**
46
+ ```ruby
47
+ "bug_tracker_uri" => "#{spec.homepage}/auditron/issues"
48
+ ```
49
+
50
+ **After:**
51
+ ```ruby
52
+ "bug_tracker_uri" => "#{spec.homepage}/issues"
53
+ ```
54
+
55
+ #### `response_builder.rb` — removed stale commented-out code
56
+ A dead `build_meta` implementation was left commented out from a previous
57
+ refactor. Removed to keep the file clean and readable.
58
+
59
+ ---
60
+
3
61
  ## [2.1.0] — Interactive Install Generator
4
62
 
5
63
  ### Added
data/README.md CHANGED
@@ -143,8 +143,9 @@ Error responses additionally include:
143
143
 
144
144
  | Key | Type | Description |
145
145
  |----------|------|--------------------------------------|
146
- | `errors` | Hash | Field-level errors `{field: [msgs]}` |
147
- | `errors` | Hash | Field-level errors `{field: msgs}` |
146
+ | `errors` | Hash | Field-level errors `{ field: ["message", ...] }` |
147
+
148
+ > **`errors` is optional.** Pass it when you want to surface field-level detail to the client (e.g. form validation, token issues). Omit it for simple human-readable-only responses — `message` alone is perfectly valid.
148
149
 
149
150
  ---
150
151
 
@@ -304,222 +305,386 @@ render_permanent_redirect(message: "Permanently moved — update your bookmarks"
304
305
 
305
306
  ### 4xx — Client Error Helpers
306
307
 
308
+ > **Two usage patterns for every error helper:**
309
+ > - **Message only** — a human-readable string shown to the end user.
310
+ > - **Message + errors** — add `errors:` when you also need field-level detail for the client to act on (e.g. highlight a form field, log a specific token issue). `errors` is a Hash of `{ field: ["message", ...] }`.
311
+
307
312
  #### `render_bad_request` — 400 Bad Request
308
313
  ```ruby
314
+ # Message only
309
315
  render_bad_request(message: "The 'date' parameter is required")
310
- render_bad_request(message: "Invalid input", errors: { date: ["must be a valid date"] })
316
+
317
+ # Message + errors
318
+ render_bad_request(message: "Invalid input", errors: { date: "must be a valid date"})
311
319
  ```
312
320
 
313
321
  #### `render_unauthorized` — 401 Unauthorized
314
322
  ```ruby
323
+ # Message only
315
324
  render_unauthorized(message: "Please log in to continue")
316
- render_unauthorized(message: "Token has expired")
325
+
326
+ # Message + errors
327
+ render_unauthorized(message: "Token has expired", errors: { token: "has expired, please log in again"})
317
328
  ```
318
329
 
319
330
  #### `render_payment_required` — 402 Payment Required
320
331
  ```ruby
332
+ # Message only
321
333
  render_payment_required(message: "Upgrade to Pro to access this feature")
334
+
335
+ # Message + errors
336
+ render_payment_required( message: "Upgrade to Pro to access this feature", errors: { plan: "must be Pro or higher to access this feature"})
322
337
  ```
323
338
 
324
339
  #### `render_forbidden` — 403 Forbidden
325
340
  ```ruby
341
+ # Message only
326
342
  render_forbidden(message: "You can only edit your own posts")
343
+
344
+ # Message + errors
345
+ render_forbidden(message: "You can only edit your own posts",errors: { post: "does not belong to you" })
327
346
  ```
328
347
 
329
348
  #### `render_not_found` — 404 Not Found
330
349
  ```ruby
350
+ # Message only
331
351
  render_not_found(message: "User not found")
332
- render_not_found(message: "Post ##{params[:id]} does not exist")
352
+
353
+ # Message + errors
354
+ render_not_found(message: "User not found", errors: { id: "no user exists with this ID" })
333
355
  ```
334
356
 
335
357
  #### `render_method_not_allowed` — 405
336
358
  ```ruby
359
+ # Message only
337
360
  render_method_not_allowed(message: "This endpoint only accepts POST requests")
361
+
362
+ # Message + errors
363
+ render_method_not_allowed(message: "This endpoint only accepts POST requests",errors: { method: "GET is not allowed, use POST" })
338
364
  ```
339
365
 
340
366
  #### `render_not_acceptable` — 406
341
367
  ```ruby
368
+ # Message only
342
369
  render_not_acceptable(message: "Only application/json is supported")
370
+
371
+ # Message + errors
372
+ render_not_acceptable(message: "Only application/json is supported", errors: { content_type: "must be application/json" })
343
373
  ```
344
374
 
345
375
  #### `render_proxy_auth_required` — 407
346
376
  ```ruby
377
+ # Message only
347
378
  render_proxy_auth_required(message: "Authenticate with the proxy first")
379
+
380
+ # Message + errors
381
+ render_proxy_auth_required(message: "Authenticate with the proxy first", errors: { proxy_token: "is missing or invalid"})
348
382
  ```
349
383
 
350
384
  #### `render_request_timeout` — 408
351
385
  ```ruby
386
+ # Message only
352
387
  render_request_timeout(message: "The query took too long. Try a smaller date range.")
388
+
389
+ # Message + errors
390
+ render_request_timeout( message: "The query took too long. Try a smaller date range.", errors: { date_range: "must span 90 days or fewer" })
353
391
  ```
354
392
 
355
393
  #### `render_conflict` — 409 Conflict
356
394
  ```ruby
395
+ # Message only
357
396
  render_conflict(message: "Email address is already registered")
358
- render_conflict(message: "Duplicate entry", errors: { email: ["has already been taken"] })
397
+
398
+ # Message + errors
399
+ render_conflict(message: "Email address is already registered",errors: { email: "has already been taken" })
359
400
  ```
360
401
 
361
402
  #### `render_gone` — 410 Gone
362
403
  ```ruby
404
+ # Message only
363
405
  render_gone(message: "This account has been permanently deleted")
406
+
407
+ # Message + errors
408
+ render_gone(message: "This account has been permanently deleted",errors: { account: ["no longer exists and cannot be recovered"] })
364
409
  ```
365
410
 
366
411
  #### `render_length_required` — 411
367
412
  ```ruby
413
+ # Message only
368
414
  render_length_required(message: "Content-Length header is required")
415
+
416
+ # Message + errors
417
+ render_length_required(message: "Content-Length header is required",errors: { content_length: ["header is missing from the request"] })
369
418
  ```
370
419
 
371
420
  #### `render_precondition_failed` — 412
372
421
  ```ruby
422
+ # Message only
373
423
  render_precondition_failed(message: "Resource has been modified since your last request")
424
+
425
+ # Message + errors
426
+ render_precondition_failed(message: "Resource has been modified since your last request",errors: { etag: ["does not match the current resource version"] })
374
427
  ```
375
428
 
376
429
  #### `render_payload_too_large` — 413
377
430
  ```ruby
431
+ # Message only
378
432
  render_payload_too_large(message: "File exceeds the 10 MB upload limit")
433
+
434
+ # Message + errors
435
+ render_payload_too_large(message: "File exceeds the 10 MB upload limit",errors: { file: ["must be smaller than 10 MB"] })
379
436
  ```
380
437
 
381
438
  #### `render_uri_too_long` — 414
382
439
  ```ruby
440
+ # Message only
383
441
  render_uri_too_long(message: "That URL is too long to process")
442
+
443
+ # Message + errors
444
+ render_uri_too_long(message: "That URL is too long to process",errors: { url: ["must not exceed 2048 characters"] })
384
445
  ```
385
446
 
386
447
  #### `render_unsupported_media_type` — 415
387
448
  ```ruby
449
+ # Message only
388
450
  render_unsupported_media_type(message: "Please send requests as application/json")
451
+
452
+ # Message + errors
453
+ render_unsupported_media_type(message: "Please send requests as application/json",errors: { content_type: ["must be application/json, got text/xml"] })
389
454
  ```
390
455
 
391
456
  #### `render_range_not_satisfiable` — 416
392
457
  ```ruby
458
+ # Message only
393
459
  render_range_not_satisfiable(message: "Requested byte range is out of bounds")
460
+
461
+ # Message + errors
462
+ render_range_not_satisfiable(message: "Requested byte range is out of bounds", errors: { range: ["exceeds the total file size"] })
394
463
  ```
395
464
 
396
465
  #### `render_expectation_failed` — 417
397
466
  ```ruby
467
+ # Message only
398
468
  render_expectation_failed(message: "Expect header value cannot be met")
469
+
470
+ # Message + errors
471
+ render_expectation_failed(message: "Expect header value cannot be met",errors: { expect: ["100-continue is not supported on this endpoint"] })
399
472
  ```
400
473
 
401
474
  #### `render_im_a_teapot` — 418
402
475
  ```ruby
476
+ # Message only
403
477
  render_im_a_teapot(message: "I'm a teapot — I cannot brew coffee")
478
+
479
+ # Message + errors
480
+ render_im_a_teapot(message: "I'm a teapot — I cannot brew coffee",errors: { beverage: ["coffee is not supported, try tea"] })
404
481
  ```
405
482
 
406
483
  #### `render_misdirected_request` — 421
407
484
  ```ruby
485
+ # Message only
408
486
  render_misdirected_request(message: "Request sent to the wrong server")
487
+
488
+ # Message + errors
489
+ render_misdirected_request(message: "Request sent to the wrong server",errors: { host: ["this server does not handle requests for this host"] })
409
490
  ```
410
491
 
411
492
  #### `render_unprocessable` — 422 Unprocessable Entity
412
493
  Validation errors. The most commonly used error helper in Rails APIs.
413
494
 
414
495
  ```ruby
415
- render_unprocessable(message: "Validation failed", errors: user.errors)
416
- render_unprocessable(message: "Invalid data", errors: { name: ["can't be blank"] })
496
+ # Message only
497
+ render_unprocessable(message: "Validation failed")
498
+
499
+ # Message + errors — pass an ActiveModel::Errors object directly
500
+ render_unprocessable(message: "Validation failed",errors: user.errors)
501
+
502
+ # Message + errors — pass a plain hash
503
+ render_unprocessable(message: "Invalid data",errors: { name: ["can't be blank"], email: ["is invalid"] })
417
504
  ```
418
505
 
419
506
  #### `render_locked` — 423
420
507
  ```ruby
508
+ # Message only
421
509
  render_locked(message: "This record is locked by another user")
510
+
511
+ # Message + errors
512
+ render_locked(message: "This record is locked by another user",errors: { record: ["is currently locked, try again later"] })
422
513
  ```
423
514
 
424
515
  #### `render_failed_dependency` — 424
425
516
  ```ruby
517
+ # Message only
426
518
  render_failed_dependency(message: "Prerequisite resource creation failed")
519
+
520
+ # Message + errors
521
+ render_failed_dependency(message: "Prerequisite resource creation failed",errors: { dependency: ["parent record must exist before creating this resource"] })
427
522
  ```
428
523
 
429
524
  #### `render_too_early` — 425
430
525
  ```ruby
526
+ # Message only
431
527
  render_too_early(message: "Request may be a replay — rejected for safety")
528
+
529
+ # Message + errors
530
+ render_too_early(message: "Request may be a replay — rejected for safety",errors: { request: ["early data replay detected, resend after handshake"] })
432
531
  ```
433
532
 
434
533
  #### `render_upgrade_required` — 426
435
534
  ```ruby
535
+ # Message only
436
536
  render_upgrade_required(message: "Please upgrade to TLS 1.3")
537
+
538
+ # Message + errors
539
+ render_upgrade_required(message: "Please upgrade to TLS 1.3",errors: { protocol: ["TLS 1.2 is no longer supported, upgrade to TLS 1.3"] })
437
540
  ```
438
541
 
439
542
  #### `render_precondition_required` — 428
440
543
  ```ruby
544
+ # Message only
441
545
  render_precondition_required(message: "Include an If-Match header with your request")
546
+
547
+ # Message + errors
548
+ render_precondition_required(message: "Include an If-Match header with your request",errors: { if_match: ["header is required to prevent lost updates"] })
442
549
  ```
443
550
 
444
551
  #### `render_too_many_requests` — 429
445
552
  ```ruby
553
+ # Message only
446
554
  render_too_many_requests(message: "You have exceeded 100 requests per minute.")
447
- render_too_many_requests(message: "Rate limit hit", meta: { retry_after: 60 })
555
+
556
+ # Message + errors
557
+ render_too_many_requests(message: "Rate limit exceeded",errors: { rate_limit: ["100 requests per minute allowed, retry after 60 seconds"] },meta: { retry_after: 60 })
448
558
  ```
449
559
 
450
560
  #### `render_request_header_fields_too_large` — 431
451
561
  ```ruby
562
+ # Message only
452
563
  render_request_header_fields_too_large(message: "Cookie header is too large")
564
+
565
+ # Message + errors
566
+ render_request_header_fields_too_large(message: "Cookie header is too large",errors: { cookie: ["must not exceed 4096 bytes"] })
453
567
  ```
454
568
 
455
569
  #### `render_unavailable_for_legal_reasons` — 451
456
570
  ```ruby
571
+ # Message only
457
572
  render_unavailable_for_legal_reasons(message: "This content is blocked in your region")
573
+
574
+ # Message + errors
575
+ render_unavailable_for_legal_reasons(message: "This content is blocked in your region",errors: { region: ["content is not licensed for distribution in your country"] })
458
576
  ```
459
577
 
460
578
  ---
461
579
 
462
580
  ### 5xx — Server Error Helpers
463
581
 
582
+ > **Two usage patterns for every error helper:**
583
+ > - **Message only** — a human-readable string shown to the end user.
584
+ > - **Message + errors** — add `errors:` when you need to surface internal detail for debugging or logging (e.g. which downstream service failed). `errors` is a Hash of `{ field: ["message", ...] }`.
585
+
464
586
  #### `render_server_error` — 500 Internal Server Error
465
587
  ```ruby
588
+ # Message only
466
589
  render_server_error(message: "Something went wrong. Our team has been notified.")
467
590
 
591
+ # Message + errors
592
+ render_server_error(message: "Something went wrong. Our team has been notified.",errors: { server: ["unexpected exception in OrdersController#create"] })
593
+
468
594
  # Common pattern — rescue unexpected exceptions
469
595
  rescue StandardError => e
470
596
  Rails.logger.error(e)
471
- render_server_error("An unexpected error occurred")
597
+ render_server_error(message: "An unexpected error occurred",errors: { server: [e.message] })
472
598
  ```
473
599
 
474
600
  #### `render_not_implemented` — 501
475
601
  ```ruby
602
+ # Message only
476
603
  render_not_implemented(message: "CSV export is coming soon")
604
+
605
+ # Message + errors
606
+ render_not_implemented(message: "CSV export is coming soon",errors: { format: ["csv export is not yet implemented, use json"] })
477
607
  ```
478
608
 
479
609
  #### `render_bad_gateway` — 502
480
610
  ```ruby
611
+ # Message only
481
612
  render_bad_gateway(message: "Payment gateway is currently unavailable")
613
+
614
+ # Message + errors
615
+ render_bad_gateway(message: "Payment gateway is currently unavailable",errors: { gateway: ["Stripe returned a 502, please try again"] })
482
616
  ```
483
617
 
484
618
  #### `render_service_unavailable` — 503
485
619
  ```ruby
620
+ # Message only
486
621
  render_service_unavailable(message: "Down for maintenance. Back in 30 minutes.")
487
- render_service_unavailable(message: "Maintenance window", meta: { retry_after: 1800 })
622
+
623
+ # Message + errors
624
+ render_service_unavailable(message: "Down for maintenance. Back in 30 minutes.",errors: { service: ["scheduled maintenance window until 03:00 UTC"] },meta: { retry_after: 1800 })
488
625
  ```
489
626
 
490
627
  #### `render_gateway_timeout` — 504
491
628
  ```ruby
629
+ # Message only
492
630
  render_gateway_timeout(message: "The payment processor did not respond in time.")
631
+
632
+ # Message + errors
633
+ render_gateway_timeout(message: "The payment processor did not respond in time.",errors: { gateway: ["upstream timeout after 30 seconds, you have not been charged"] })
493
634
  ```
494
635
 
495
636
  #### `render_http_version_not_supported` — 505
496
637
  ```ruby
638
+ # Message only
497
639
  render_http_version_not_supported(message: "Only HTTP/1.1 and HTTP/2 are supported")
640
+
641
+ # Message + errors
642
+ render_http_version_not_supported(message: "Only HTTP/1.1 and HTTP/2 are supported",errors: { http_version: ["HTTP/1.0 is not supported"] })
498
643
  ```
499
644
 
500
645
  #### `render_variant_also_negotiates` — 506
501
646
  ```ruby
647
+ # Message only
502
648
  render_variant_also_negotiates(message: "Server content-negotiation loop detected")
649
+
650
+ # Message + errors
651
+ render_variant_also_negotiates(message: "Server content-negotiation loop detected",errors: { variant: ["misconfigured content negotiation caused an infinite loop"] })
503
652
  ```
504
653
 
505
654
  #### `render_insufficient_storage` — 507
506
655
  ```ruby
656
+ # Message only
507
657
  render_insufficient_storage(message: "Disk quota exceeded on this node")
658
+
659
+ # Message + errors
660
+ render_insufficient_storage(message: "Disk quota exceeded on this node",errors: { storage: ["upload failed, node has 0 bytes remaining"] })
508
661
  ```
509
662
 
510
663
  #### `render_loop_detected` — 508
511
664
  ```ruby
665
+ # Message only
512
666
  render_loop_detected(message: "Infinite redirect loop detected")
667
+
668
+ # Message + errors
669
+ render_loop_detected(message: "Infinite redirect loop detected",errors: { redirect: ["request visited the same URL more than 10 times"] })
513
670
  ```
514
671
 
515
672
  #### `render_not_extended` — 510
516
673
  ```ruby
674
+ # Message only
517
675
  render_not_extended(message: "Further extensions required to fulfil this request")
676
+
677
+ # Message + errors
678
+ render_not_extended(message: "Further extensions required to fulfil this request",errors: { extension: ["mandatory extension 'auth' is missing from the request"] })
518
679
  ```
519
680
 
520
681
  #### `render_network_authentication_required` — 511
521
682
  ```ruby
683
+ # Message only
522
684
  render_network_authentication_required(message: "Sign in to the network portal first")
685
+
686
+ # Message + errors
687
+ render_network_authentication_required(message: "Sign in to the network portal first",errors: { network: ["captive portal authentication required before accessing the API"] })
523
688
  ```
524
689
 
525
690
  ---
@@ -539,12 +704,12 @@ class UsersController < ApplicationController
539
704
  data: @users,
540
705
  message: "Users fetched",
541
706
  pagination: {
542
- per_page: per_page.to_i,
543
- current_page: @users.current_page,
544
- next_page: @users.next_page,
545
- prev_page: @users.prev_page,
546
- total_pages: @users.total_pages,
547
- total_count: @users.total_count
707
+ per_page: per_page.to_i,
708
+ current_page: @users.current_page,
709
+ next_page: @users.next_page,
710
+ prev_page: @users.prev_page,
711
+ total_pages: @users.total_pages,
712
+ total_count: @users.total_count
548
713
  }
549
714
  )
550
715
  end
@@ -553,7 +718,7 @@ class UsersController < ApplicationController
553
718
  user = User.find(params[:id])
554
719
  render_ok(data: user, message: "User found")
555
720
  rescue ActiveRecord::RecordNotFound
556
- render_not_found(message: "User ##{params[:id]} not found", error: { id: "User #{params[:id]} not exist"})
721
+ render_not_found(message: "User ##{params[:id]} not found",errors: { id: ["no user exists with ID #{params[:id]}"] })
557
722
  end
558
723
 
559
724
  def create
@@ -569,7 +734,7 @@ class UsersController < ApplicationController
569
734
  user = User.find(params[:id])
570
735
 
571
736
  unless user == current_user || current_user.admin?
572
- render_forbidden(message: "You can only update your own profile", error: { profile: "update your own profile" })
737
+ render_forbidden( message: "You can only update your own profile", errors: { profile: ["you do not have permission to update this profile"] } )
573
738
  return
574
739
  end
575
740
 
@@ -595,11 +760,11 @@ class PaymentsController < ApplicationController
595
760
  result = PaymentGateway.charge(amount: params[:amount], token: params[:token])
596
761
  render_created(data: result, message: "Payment successful")
597
762
  rescue PaymentGateway::CardDeclined => e
598
- render_unprocessable(message: e.message)
763
+ render_unprocessable(message: e.message, errors: { card: [e.message] })
599
764
  rescue PaymentGateway::Timeout
600
- render_gateway_timeout(message: "Payment processor timed out. You have not been charged.")
765
+ render_gateway_timeout( message: "Payment processor timed out. You have not been charged.", errors: { gateway: ["upstream timeout, transaction was not processed"] } )
601
766
  rescue PaymentGateway::Error => e
602
- render_bad_gateway(message: "Payment gateway error: #{e.message}")
767
+ render_bad_gateway( message: "Payment gateway error: #{e.message}", errors: { gateway: [e.message] })
603
768
  end
604
769
 
605
770
  end
@@ -700,7 +865,7 @@ render_ok(data: @user, message: "User found")
700
865
 
701
866
  ```ruby
702
867
  # Core
703
- render_success(data:, message:, meta:, code:, pagination:, code:, status:)
868
+ render_success(data:, message:, meta:, pagination:, code:, status:)
704
869
  render_error(message:, errors:, code:, meta:, status:)
705
870
 
706
871
  # 1xx — Informational
@@ -710,7 +875,7 @@ render_processing(message:, meta:)
710
875
  render_early_hints(message:, meta:)
711
876
 
712
877
  # 2xx — Success
713
- render_success(data:, message:, meta:, pagination:, code: , status:)
878
+ render_success(data:, message:, meta:, pagination:, code:, status:)
714
879
  render_ok(data:, message:, meta:, pagination:)
715
880
  render_created(data:, message:, meta:, pagination:)
716
881
  render_accepted(data:, message:, meta:, pagination:)
@@ -146,7 +146,7 @@ module Respondo
146
146
  # 204 No Content — deletions, actions with no response body
147
147
  # Note: we still return our standard JSON structure for consistency
148
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)
149
+ render_success(data: nil, message: message, meta: meta, pagination: pagination, code: 204, status: :no_content)
150
150
  end
151
151
 
152
152
  # 205 Reset Content — tell the client to reset the document view
@@ -97,28 +97,6 @@ module Respondo
97
97
  meta
98
98
  end
99
99
 
100
- # def build_meta
101
- # meta = { timestamp: current_timestamp }
102
-
103
- # # Only extract pagination when caller has not explicitly disabled it
104
- # if @pagination
105
- # pagination = if @pagy
106
- # Pagination.extract(@pagy)
107
- # else
108
- # Pagination.extract(@raw_data)
109
- # end
110
- # meta[:pagination] = pagination if pagination
111
- # end
112
-
113
- # # Request ID (Rails only, opt-in via config)
114
- # if Respondo.config.include_request_id && @request&.respond_to?(:request_id)
115
- # meta[:request_id] = @request.request_id
116
- # end
117
-
118
- # # Merge any caller-supplied meta last (allows overriding)
119
- # meta.merge(@extra_meta)
120
- # end
121
-
122
100
  def current_timestamp
123
101
  if defined?(Time.current)
124
102
  Time.current.iso8601
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Respondo
4
- VERSION = "2.1.0"
4
+ VERSION = "2.1.1"
5
5
  end
data/respondo.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  "homepage_uri" => spec.homepage,
24
24
  "source_code_uri" => spec.homepage,
25
25
  "changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md",
26
- "bug_tracker_uri" => "#{spec.homepage}/auditron/issues",
26
+ "bug_tracker_uri" => "#{spec.homepage}/issues",
27
27
  "rubygems_mfa_required" => "true"
28
28
  }
29
29
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: respondo
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.1.1
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-13 00:00:00.000000000 Z
11
+ date: 2026-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -110,7 +110,7 @@ metadata:
110
110
  homepage_uri: https://github.com/spatelpatidar/respondo
111
111
  source_code_uri: https://github.com/spatelpatidar/respondo
112
112
  changelog_uri: https://github.com/spatelpatidar/respondo/blob/main/CHANGELOG.md
113
- bug_tracker_uri: https://github.com/spatelpatidar/respondo/auditron/issues
113
+ bug_tracker_uri: https://github.com/spatelpatidar/respondo/issues
114
114
  rubygems_mfa_required: 'true'
115
115
  post_install_message:
116
116
  rdoc_options: []