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 +4 -4
- data/config/default.yml +9 -1
- data/lib/rubocop/cop/dev_doc/style/avoid_head_response.rb +28 -9
- data/lib/rubocop/dev_doc/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1f6961dde0d54631bae2f2dae6325183cc678f81701aa06575abab88cc1b0f7b
|
|
4
|
+
data.tar.gz: cc20cca8c229dca80fbd57d9950794b71560ccb2c13e0ace82c9b6cab0a0c93c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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;
|
|
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
|
-
#
|
|
14
|
-
#
|
|
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
|
-
#
|
|
36
|
+
# ❌ Bodyless success — a 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
|
-
# #
|
|
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
|
-
|
|
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
|
-
|
|
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
|
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.
|
|
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-
|
|
11
|
+
date: 2026-08-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|