rubocop-dev_doc 0.13.2 → 0.14.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5792a89cab7f1814ee9633da4b5c4150e2c281967aa3b718213aeca1d5eea921
4
- data.tar.gz: fcdb36d319b4aae6389cc665fade58bc7093890249f371d28bd3439e844841e0
3
+ metadata.gz: 1f6961dde0d54631bae2f2dae6325183cc678f81701aa06575abab88cc1b0f7b
4
+ data.tar.gz: cc20cca8c229dca80fbd57d9950794b71560ccb2c13e0ace82c9b6cab0a0c93c
5
5
  SHA512:
6
- metadata.gz: a5736e1156b6e7535bbe62089bd4d0f197b249df25b0fe4949c4dea682725a536cf211292728398ba68cdb455456a23de761c311f12da00e0b33eb3610e30555
7
- data.tar.gz: c8a1ecc40eedfd40c9f553a2867a34032bdb37abdbb981204a419036acf9160c0e5b45938718166d84429f65425fd70754c2630f259607dd431017d5d7bd178a
6
+ metadata.gz: cdf5e192d7d3b526311ca7e9b6d6d3d81a50b3a14d8bd9b4b4a5d4459c0ed4d34c4695e1087e109614cf6f5dc040a12b0e7686f4e4cf509e16f4c9b770a0ccfa
7
+ data.tar.gz: 3664cc36ac24eb3f1a0bd6061a3671c32695113d50dd87753a35ec13536d02330fa7f10c7188439e90726a9b3a80dac227205cbaf88f539cb668dd7d18ea628d
data/config/default.yml CHANGED
@@ -250,10 +250,14 @@ DevDoc/Style/TapBlockIgnoresValue:
250
250
  Enabled: true
251
251
 
252
252
  DevDoc/Style/AvoidHeadResponse:
253
- Description: "Avoid `head()` with error statuses; delegate error handling to Rails exceptions or model validations."
253
+ Description: "Avoid `head()` with error or no-content statuses; render a body (an exception page, validation errors, or an action spec) instead."
254
254
  Enabled: true
255
255
  Include:
256
256
  - "app/controllers/**/*.rb"
257
+ # Error statuses: delegate to Rails exceptions / model validations.
258
+ # No-content "successes" (no_content/reset_content): a bodyless response is
259
+ # ambiguous to a backend-driven JSON client -- render an action response,
260
+ # even an empty one.
257
261
  FlaggedStatuses:
258
262
  - not_found
259
263
  - unprocessable_entity
@@ -263,6 +267,8 @@ DevDoc/Style/AvoidHeadResponse:
263
267
  - conflict
264
268
  - gone
265
269
  - method_not_allowed
270
+ - no_content
271
+ - reset_content
266
272
  - "404"
267
273
  - "422"
268
274
  - "403"
@@ -271,6 +277,8 @@ DevDoc/Style/AvoidHeadResponse:
271
277
  - "409"
272
278
  - "410"
273
279
  - "405"
280
+ - "204"
281
+ - "205"
274
282
 
275
283
  DevDoc/Migration/AvoidConditionalSchemaChanges:
276
284
  Description: "Avoid conditional schema helpers (`add_column_if_not_exists`, `column_exists?`, etc.) in migrations."
@@ -2,7 +2,7 @@ module RuboCop
2
2
  module Cop
3
3
  module DevDoc
4
4
  module Style
5
- # Avoid `head()` with error status codes in controllers.
5
+ # Avoid `head()` with error or no-content status codes in controllers.
6
6
  #
7
7
  # ## Rationale
8
8
  # Using `head()` for error responses returns an empty body with no
@@ -10,8 +10,15 @@ module RuboCop
10
10
  # to Rails exceptions (e.g. `ActiveRecord::RecordNotFound`) or model
11
11
  # validations instead, which give the client more context.
12
12
  #
13
- # Success statuses like `:ok`, `:no_content`, and `:accepted` are
14
- # legitimate uses of `head()` and are not flagged.
13
+ # `head :no_content` (and `:reset_content`) is flagged for a different
14
+ # reason: in a backend-driven JSON UI a bodyless "success" is
15
+ # ambiguous — the client needs a response body (even an empty action
16
+ # spec) to know what to do. A production `head :no_content` escape
17
+ # hatch surfaced as an error snackbar in front of a customer before
18
+ # this was flagged.
19
+ #
20
+ # Success statuses that normally carry a body (`:ok`, `:accepted`)
21
+ # are legitimate uses of `head()` and are not flagged.
15
22
  #
16
23
  # The set of flagged statuses is configurable via `FlaggedStatuses:`.
17
24
  #
@@ -26,12 +33,18 @@ module RuboCop
26
33
  # @user = User.find(params[:id])
27
34
  # end
28
35
  #
29
- # ✔️ Success responseempty body is correct here
36
+ # Bodyless successa JSON-driven client learns nothing
30
37
  # def destroy
31
38
  # @resource.destroy!
32
39
  # head :no_content
33
40
  # end
34
41
  #
42
+ # ✔️ Tell the client what to do, even when that is "nothing"
43
+ # def destroy
44
+ # @resource.destroy!
45
+ # render json: {}
46
+ # end
47
+ #
35
48
  # @example
36
49
  # # bad
37
50
  # head(:not_found)
@@ -39,10 +52,10 @@ module RuboCop
39
52
  # # bad
40
53
  # head(:unprocessable_entity)
41
54
  #
42
- # # good (success status not flagged)
55
+ # # bad (bodyless success — ambiguous to a JSON-driven client)
43
56
  # head(:no_content)
44
57
  #
45
- # # good (success status — not flagged)
58
+ # # good (success status with a body expected — not flagged)
46
59
  # head(:ok)
47
60
  #
48
61
  # # good (dynamic status — not flagged to avoid false positives)
@@ -51,13 +64,18 @@ module RuboCop
51
64
  MSG = 'Avoid `head(%<status>s)` for error handling. ' \
52
65
  'Delegate to Rails exceptions or model validations instead.'.freeze
53
66
 
67
+ NO_CONTENT_MSG = 'Avoid `head(%<status>s)`: a bodyless response tells a JSON-driven ' \
68
+ 'client nothing. Render an action response (even an empty one) instead.'.freeze
69
+
54
70
  RESTRICT_ON_SEND = %i[head].freeze
55
71
 
56
- DEFAULT_FLAGGED_STATUSES = %w[
72
+ NO_CONTENT_STATUSES = %w[no_content reset_content 204 205].freeze
73
+
74
+ DEFAULT_FLAGGED_STATUSES = (%w[
57
75
  not_found unprocessable_entity forbidden unauthorized
58
76
  bad_request conflict gone method_not_allowed
59
77
  404 422 403 401 400 409 410 405
60
- ].freeze
78
+ ] + NO_CONTENT_STATUSES).freeze
61
79
 
62
80
  def on_send(node)
63
81
  # `self.head(...)` is the same controller call — a bare receiver
@@ -68,7 +86,8 @@ module RuboCop
68
86
  return unless status_node
69
87
  return unless flagged_literal?(status_node)
70
88
 
71
- add_offense(node.loc.selector, message: format(MSG, status: status_display(status_node)))
89
+ template = NO_CONTENT_STATUSES.include?(status_node.value.to_s) ? NO_CONTENT_MSG : MSG
90
+ add_offense(node.loc.selector, message: format(template, status: status_display(status_node)))
72
91
  end
73
92
 
74
93
  private
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module DevDoc
3
- VERSION = "0.13.2".freeze
3
+ VERSION = "0.14.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-dev_doc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.2
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dev-doc contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-06 00:00:00.000000000 Z
11
+ date: 2026-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport