rubocop-asjer 0.4.1 → 0.4.2
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/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +7 -0
- data/config/default.yml +46 -8
- data/lib/rubocop/asjer/version.rb +1 -1
- data/lib/rubocop/cop/asjer/rails_class_order.rb +87 -35
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 447e874612f95f1d94bce6efa0da2fcfe9e06c1b72f624fb707ddc147c5280c3
|
|
4
|
+
data.tar.gz: a815ca7e0101b2e2d1bac4bfed12718ef10e95da304dfafa83c2bc74ef10b094
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 59c42f2eb2390c5356d9afbe628a48652707c9ff3527306e2e83c29e48e9fbd04f1cfefd01f0d6b7d6da06198777d4a31721f2cce51319652ba24325d93a71a7
|
|
7
|
+
data.tar.gz: f0486413521d14aded52af6e496addd3f015c44ca832e393bb445b127c065f82e0aa0d3e906dd72bcda71439f5a451fbf68729afb89dec09182e7de06639d81a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.2](https://github.com/asjer/rubocop-asjer/compare/v0.4.1...v0.4.2) (2026-01-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* add missing rails classes to `RailsClassOrder` cop configuration ([0ddc16a](https://github.com/asjer/rubocop-asjer/commit/0ddc16a165530b0aa5c4e0d37195324779fca9a8))
|
|
9
|
+
|
|
3
10
|
## [0.4.1](https://github.com/asjer/rubocop-asjer/compare/v0.4.0...v0.4.1) (2026-01-28)
|
|
4
11
|
|
|
5
12
|
|
data/config/default.yml
CHANGED
|
@@ -9,33 +9,71 @@ Asjer/RailsClassOrder:
|
|
|
9
9
|
VersionAdded: "0.4.0"
|
|
10
10
|
Include:
|
|
11
11
|
- 'app/models/**/*.rb'
|
|
12
|
+
Scopes:
|
|
13
|
+
- default_scope
|
|
14
|
+
- scope
|
|
15
|
+
Attributes:
|
|
16
|
+
- attr_accessor
|
|
17
|
+
- attr_reader
|
|
18
|
+
- attr_writer
|
|
19
|
+
- attr_readonly
|
|
20
|
+
- attribute
|
|
21
|
+
- serialize
|
|
22
|
+
- store
|
|
23
|
+
- store_accessor
|
|
24
|
+
Enums:
|
|
25
|
+
- enum
|
|
12
26
|
Associations:
|
|
13
27
|
- belongs_to
|
|
14
|
-
- has_many
|
|
15
28
|
- has_one
|
|
29
|
+
- has_many
|
|
16
30
|
- has_and_belongs_to_many
|
|
31
|
+
- has_one_attached
|
|
32
|
+
- has_many_attached
|
|
33
|
+
Validations:
|
|
34
|
+
- validates
|
|
35
|
+
- validates_acceptance_of
|
|
36
|
+
- validates_associated
|
|
37
|
+
- validates_comparison_of
|
|
38
|
+
- validates_confirmation_of
|
|
39
|
+
- validates_each
|
|
40
|
+
- validates_exclusion_of
|
|
41
|
+
- validates_format_of
|
|
42
|
+
- validates_inclusion_of
|
|
43
|
+
- validates_length_of
|
|
44
|
+
- validates_size_of
|
|
45
|
+
- validates_numericality_of
|
|
46
|
+
- validates_presence_of
|
|
47
|
+
- validates_uniqueness_of
|
|
48
|
+
- validates_with
|
|
49
|
+
- validate
|
|
17
50
|
Callbacks:
|
|
18
51
|
- after_initialize
|
|
19
52
|
- after_find
|
|
20
53
|
- after_touch
|
|
21
54
|
- before_validation
|
|
22
|
-
- validates
|
|
23
|
-
- validate
|
|
24
55
|
- after_validation
|
|
25
56
|
- before_save
|
|
26
57
|
- around_save
|
|
27
58
|
- before_create
|
|
28
59
|
- around_create
|
|
60
|
+
- after_create
|
|
29
61
|
- before_update
|
|
30
62
|
- around_update
|
|
63
|
+
- after_update
|
|
64
|
+
- after_save
|
|
31
65
|
- before_destroy
|
|
32
66
|
- around_destroy
|
|
33
67
|
- after_destroy
|
|
34
|
-
- after_update
|
|
35
|
-
- after_create
|
|
36
|
-
- after_save
|
|
37
68
|
- after_commit
|
|
38
69
|
- after_rollback
|
|
39
70
|
Others:
|
|
40
|
-
-
|
|
41
|
-
-
|
|
71
|
+
- encrypts
|
|
72
|
+
- normalizes
|
|
73
|
+
- delegate
|
|
74
|
+
- delegate_missing_to
|
|
75
|
+
- accepts_nested_attributes_for
|
|
76
|
+
- has_secure_password
|
|
77
|
+
- has_secure_token
|
|
78
|
+
- generates_token_for
|
|
79
|
+
- composed_of
|
|
@@ -5,11 +5,12 @@ module RuboCop
|
|
|
5
5
|
module Asjer
|
|
6
6
|
# Enforces consistent ordering of declarative methods in Rails models.
|
|
7
7
|
#
|
|
8
|
-
# Methods are grouped into
|
|
9
|
-
#
|
|
10
|
-
#
|
|
8
|
+
# Methods are grouped into seven categories following Rails Style Guide:
|
|
9
|
+
# scopes, attributes, enums, associations, validations, callbacks, and others.
|
|
10
|
+
# Within each category, methods are sorted by their position in the configured list.
|
|
11
|
+
# Groups are separated by blank lines.
|
|
11
12
|
#
|
|
12
|
-
# The order is: associations,
|
|
13
|
+
# The order is: scopes, attributes, enums, associations, validations, callbacks, then others.
|
|
13
14
|
#
|
|
14
15
|
# @example
|
|
15
16
|
# # bad
|
|
@@ -18,7 +19,9 @@ module RuboCop
|
|
|
18
19
|
# validate :validate_name
|
|
19
20
|
# after_create :after_create_1
|
|
20
21
|
# has_many :messages
|
|
22
|
+
# scope :active, -> { where(active: true) }
|
|
21
23
|
# attr_readonly :email
|
|
24
|
+
# enum :status, [:pending, :active]
|
|
22
25
|
# after_create :after_create_2
|
|
23
26
|
# belongs_to :role
|
|
24
27
|
# before_create :set_name
|
|
@@ -26,34 +29,64 @@ module RuboCop
|
|
|
26
29
|
#
|
|
27
30
|
# # good
|
|
28
31
|
# class User < ApplicationRecord
|
|
32
|
+
# scope :active, -> { where(active: true) }
|
|
33
|
+
#
|
|
34
|
+
# attr_readonly :email
|
|
35
|
+
#
|
|
36
|
+
# enum :status, [:pending, :active]
|
|
37
|
+
#
|
|
29
38
|
# belongs_to :plan
|
|
30
39
|
# belongs_to :role
|
|
31
40
|
# has_many :messages
|
|
32
41
|
#
|
|
33
42
|
# validate :validate_name
|
|
43
|
+
#
|
|
34
44
|
# before_create :set_name
|
|
35
45
|
# after_create :after_create_1
|
|
36
46
|
# after_create :after_create_2
|
|
37
|
-
#
|
|
38
|
-
# attr_readonly :email
|
|
39
47
|
# end
|
|
40
48
|
#
|
|
41
49
|
# Default method lists for RailsClassOrder cop
|
|
42
50
|
module RailsClassOrderDefaults
|
|
51
|
+
SCOPES = %w[default_scope scope].freeze
|
|
52
|
+
|
|
53
|
+
ATTRIBUTES = %w[
|
|
54
|
+
attr_accessor attr_reader attr_writer attr_readonly
|
|
55
|
+
attribute serialize store store_accessor
|
|
56
|
+
].freeze
|
|
57
|
+
|
|
58
|
+
ENUMS = %w[enum].freeze
|
|
59
|
+
|
|
43
60
|
ASSOCIATIONS = %w[
|
|
44
|
-
belongs_to has_many
|
|
61
|
+
belongs_to has_one has_many has_and_belongs_to_many
|
|
62
|
+
has_one_attached has_many_attached
|
|
63
|
+
].freeze
|
|
64
|
+
|
|
65
|
+
VALIDATIONS = %w[
|
|
66
|
+
validates validates_acceptance_of validates_associated
|
|
67
|
+
validates_comparison_of validates_confirmation_of validates_each
|
|
68
|
+
validates_exclusion_of validates_format_of validates_inclusion_of
|
|
69
|
+
validates_length_of validates_size_of validates_numericality_of
|
|
70
|
+
validates_presence_of validates_uniqueness_of validates_with
|
|
71
|
+
validate
|
|
45
72
|
].freeze
|
|
46
73
|
|
|
47
74
|
CALLBACKS = %w[
|
|
48
75
|
after_initialize after_find after_touch
|
|
49
|
-
before_validation
|
|
50
|
-
before_save around_save
|
|
51
|
-
|
|
52
|
-
|
|
76
|
+
before_validation after_validation
|
|
77
|
+
before_save around_save
|
|
78
|
+
before_create around_create after_create
|
|
79
|
+
before_update around_update after_update
|
|
80
|
+
after_save
|
|
81
|
+
before_destroy around_destroy after_destroy
|
|
53
82
|
after_commit after_rollback
|
|
54
83
|
].freeze
|
|
55
84
|
|
|
56
|
-
OTHERS = %w[
|
|
85
|
+
OTHERS = %w[
|
|
86
|
+
encrypts normalizes delegate delegate_missing_to
|
|
87
|
+
accepts_nested_attributes_for has_secure_password
|
|
88
|
+
has_secure_token generates_token_for composed_of
|
|
89
|
+
].freeze
|
|
57
90
|
end
|
|
58
91
|
|
|
59
92
|
# Autocorrect helpers for RailsClassOrder cop
|
|
@@ -101,8 +134,11 @@ module RuboCop
|
|
|
101
134
|
def build_sorted_source(sorted, original)
|
|
102
135
|
indent = ' ' * original.first.loc.column
|
|
103
136
|
grouped = sorted.group_by { |m| method_type(m) }
|
|
137
|
+
format_grouped_source(grouped, indent)
|
|
138
|
+
end
|
|
104
139
|
|
|
105
|
-
|
|
140
|
+
def format_grouped_source(grouped, indent)
|
|
141
|
+
self.class::TYPE_ORDER.keys.filter_map do |type|
|
|
106
142
|
next unless grouped[type]&.any?
|
|
107
143
|
|
|
108
144
|
grouped[type].map { |m| source_with_comments(m) }.join("\n#{indent}")
|
|
@@ -123,8 +159,28 @@ module RuboCop
|
|
|
123
159
|
include RangeHelp
|
|
124
160
|
include RailsClassOrderCorrector
|
|
125
161
|
|
|
126
|
-
MSG = 'Declarative methods should be sorted by type:
|
|
127
|
-
|
|
162
|
+
MSG = 'Declarative methods should be sorted by type: scopes, attributes, enums, ' \
|
|
163
|
+
'associations, validations, callbacks, then others.'
|
|
164
|
+
|
|
165
|
+
TYPE_ORDER = {
|
|
166
|
+
scope: 0,
|
|
167
|
+
attribute: 1,
|
|
168
|
+
enum: 2,
|
|
169
|
+
association: 3,
|
|
170
|
+
validation: 4,
|
|
171
|
+
callback: 5,
|
|
172
|
+
other: 6
|
|
173
|
+
}.freeze
|
|
174
|
+
|
|
175
|
+
CATEGORY_CONFIG = {
|
|
176
|
+
scope: { key: 'Scopes', const: :SCOPES },
|
|
177
|
+
attribute: { key: 'Attributes', const: :ATTRIBUTES },
|
|
178
|
+
enum: { key: 'Enums', const: :ENUMS },
|
|
179
|
+
association: { key: 'Associations', const: :ASSOCIATIONS },
|
|
180
|
+
validation: { key: 'Validations', const: :VALIDATIONS },
|
|
181
|
+
callback: { key: 'Callbacks', const: :CALLBACKS },
|
|
182
|
+
other: { key: 'Others', const: :OTHERS }
|
|
183
|
+
}.freeze
|
|
128
184
|
|
|
129
185
|
def on_class(node)
|
|
130
186
|
_name, _superclass, body = *node
|
|
@@ -146,20 +202,17 @@ module RuboCop
|
|
|
146
202
|
add_offense(first_misplaced) { |corrector| autocorrect(corrector, body, targets, sorted) }
|
|
147
203
|
end
|
|
148
204
|
|
|
149
|
-
def
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def others
|
|
158
|
-
@others ||= cop_config.fetch('Others', RailsClassOrderDefaults::OTHERS).map(&:to_sym)
|
|
205
|
+
def category_methods(category)
|
|
206
|
+
cfg = CATEGORY_CONFIG[category]
|
|
207
|
+
instance_variable_get(:"@#{category}") ||
|
|
208
|
+
instance_variable_set(
|
|
209
|
+
:"@#{category}",
|
|
210
|
+
cop_config.fetch(cfg[:key], RailsClassOrderDefaults.const_get(cfg[:const])).map(&:to_sym)
|
|
211
|
+
)
|
|
159
212
|
end
|
|
160
213
|
|
|
161
214
|
def all_target_methods
|
|
162
|
-
@all_target_methods ||=
|
|
215
|
+
@all_target_methods ||= TYPE_ORDER.keys.flat_map { |cat| category_methods(cat) }
|
|
163
216
|
end
|
|
164
217
|
|
|
165
218
|
def target_methods(body)
|
|
@@ -167,14 +220,16 @@ module RuboCop
|
|
|
167
220
|
end
|
|
168
221
|
|
|
169
222
|
def sort_methods(methods)
|
|
170
|
-
methods.each_with_index.sort_by
|
|
223
|
+
methods.each_with_index.sort_by do |method, index|
|
|
224
|
+
[method_type_order(method), method_position_in_type(method), index]
|
|
225
|
+
end.map(&:first)
|
|
171
226
|
end
|
|
172
227
|
|
|
173
228
|
def method_type(method)
|
|
174
229
|
name = method.method_name
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
230
|
+
TYPE_ORDER.each_key do |category|
|
|
231
|
+
return category if category_methods(category).include?(name)
|
|
232
|
+
end
|
|
178
233
|
:other
|
|
179
234
|
end
|
|
180
235
|
|
|
@@ -183,11 +238,8 @@ module RuboCop
|
|
|
183
238
|
end
|
|
184
239
|
|
|
185
240
|
def method_position_in_type(method)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
def method_list_for_type(type)
|
|
190
|
-
{ association: associations, callback: callbacks, other: others }[type]
|
|
241
|
+
list = category_methods(method_type(method))
|
|
242
|
+
list.index(method.method_name) || list.size
|
|
191
243
|
end
|
|
192
244
|
end
|
|
193
245
|
end
|