rubocop-rails 2.13.2 → 2.14.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/config/default.yml +69 -2
- data/lib/rubocop/cop/mixin/class_send_node_helper.rb +20 -0
- data/lib/rubocop/cop/rails/action_controller_test_case.rb +47 -0
- data/lib/rubocop/cop/rails/after_commit_override.rb +2 -12
- data/lib/rubocop/cop/rails/bulk_change_table.rb +20 -6
- data/lib/rubocop/cop/rails/compact_blank.rb +13 -5
- data/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +108 -0
- data/lib/rubocop/cop/rails/duplicate_association.rb +56 -0
- data/lib/rubocop/cop/rails/duplicate_scope.rb +46 -0
- data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +94 -0
- data/lib/rubocop/cop/rails/i18n_locale_texts.rb +110 -0
- data/lib/rubocop/cop/rails/migration_class_name.rb +63 -0
- data/lib/rubocop/cop/rails/pluck.rb +15 -7
- data/lib/rubocop/cop/rails/table_name_assignment.rb +44 -0
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +94 -0
- data/lib/rubocop/cop/rails_cops.rb +10 -0
- data/lib/rubocop/rails/version.rb +1 -1
- metadata +13 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: babf21479a37aa37cba8b6b8401b23ddb6532e14afd679095d456f749aca3ca0
|
4
|
+
data.tar.gz: 11a94f8219a5b9d241d68af1c3ecd69afb0a47ccf988db59d00f48caaf73dfbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02b2646080a54c50c8708cd6feeed501b5aafd7ae77d04e42ed0bf5b8779f43fa778bc3f46daec2c06474ac76f40ae144bf0afed35e5acf996c4b2213df53f89
|
7
|
+
data.tar.gz: 4b29b44608474ead97651327e5c896bfb403eadcc1deffd10730853f303e75682e3ebebed80f8b3b05c1f9f0862441845bea89135d694ecf70ee3d6c776f2a97
|
data/config/default.yml
CHANGED
@@ -7,7 +7,9 @@ inherit_mode:
|
|
7
7
|
AllCops:
|
8
8
|
Exclude:
|
9
9
|
- bin/*
|
10
|
-
|
10
|
+
# Exclude db/schema.rb and db/[CONFIGURATION_NAMESPACE]_schema.rb by default.
|
11
|
+
# See: https://guides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application
|
12
|
+
- db/*schema.rb
|
11
13
|
# What version of Rails is the inspected code using? If a value is specified
|
12
14
|
# for TargetRailsVersion then it is used. Acceptable values are specified
|
13
15
|
# as a float (i.e. 5.1); the patch version of Rails should not be included.
|
@@ -38,6 +40,16 @@ Lint/NumberConversion:
|
|
38
40
|
- fortnights
|
39
41
|
- in_milliseconds
|
40
42
|
|
43
|
+
Rails/ActionControllerTestCase:
|
44
|
+
Description: 'Use `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.'
|
45
|
+
StyleGuide: 'https://rails.rubystyle.guide/#integration-testing'
|
46
|
+
Reference: 'https://api.rubyonrails.org/classes/ActionController/TestCase.html'
|
47
|
+
Enabled: 'pending'
|
48
|
+
SafeAutocorrect: false
|
49
|
+
VersionAdded: '2.14'
|
50
|
+
Include:
|
51
|
+
- '**/test/**/*.rb'
|
52
|
+
|
41
53
|
Rails/ActionFilter:
|
42
54
|
Description: 'Enforces consistent use of action filter methods.'
|
43
55
|
Enabled: true
|
@@ -195,9 +207,12 @@ Rails/ContentTag:
|
|
195
207
|
Enabled: true
|
196
208
|
VersionAdded: '2.6'
|
197
209
|
VersionChanged: '2.12'
|
198
|
-
# This `Exclude` config prevents false positives for `tag` calls to `has_one: tag
|
210
|
+
# This `Exclude` config prevents false positives for `tag` calls to `has_one: tag` and Puma configuration:
|
211
|
+
# https://puma.io/puma/Puma/DSL.html#tag-instance_method
|
212
|
+
# No helpers are used in normal models and configs.
|
199
213
|
Exclude:
|
200
214
|
- app/models/**/*.rb
|
215
|
+
- config/**/*.rb
|
201
216
|
|
202
217
|
Rails/CreateTableWithTimestamps:
|
203
218
|
Description: >-
|
@@ -251,6 +266,22 @@ Rails/DelegateAllowBlank:
|
|
251
266
|
Enabled: true
|
252
267
|
VersionAdded: '0.44'
|
253
268
|
|
269
|
+
Rails/DeprecatedActiveModelErrorsMethods:
|
270
|
+
Description: 'Avoid manipulating ActiveModel errors hash directly.'
|
271
|
+
Enabled: pending
|
272
|
+
Safe: false
|
273
|
+
VersionAdded: '2.14'
|
274
|
+
|
275
|
+
Rails/DuplicateAssociation:
|
276
|
+
Description: "Don't repeat associations in a model."
|
277
|
+
Enabled: pending
|
278
|
+
VersionAdded: '2.14'
|
279
|
+
|
280
|
+
Rails/DuplicateScope:
|
281
|
+
Description: 'Multiple scopes share this same where clause.'
|
282
|
+
Enabled: pending
|
283
|
+
VersionAdded: '2.14'
|
284
|
+
|
254
285
|
Rails/DurationArithmetic:
|
255
286
|
Description: 'Do not use duration as arithmetic operand with `Time.current`.'
|
256
287
|
StyleGuide: 'https://rails.rubystyle.guide#duration-arithmetic'
|
@@ -415,6 +446,15 @@ Rails/HttpStatus:
|
|
415
446
|
- numeric
|
416
447
|
- symbolic
|
417
448
|
|
449
|
+
Rails/I18nLazyLookup:
|
450
|
+
Description: 'Checks for places where I18n "lazy" lookup can be used.'
|
451
|
+
StyleGuide: 'https://rails.rubystyle.guide/#lazy-lookup'
|
452
|
+
Reference: 'https://guides.rubyonrails.org/i18n.html#lazy-lookup'
|
453
|
+
Enabled: pending
|
454
|
+
VersionAdded: '2.14'
|
455
|
+
Include:
|
456
|
+
- 'controllers/**/*'
|
457
|
+
|
418
458
|
Rails/I18nLocaleAssignment:
|
419
459
|
Description: 'Prefer the usage of `I18n.with_locale` instead of manually updating `I18n.locale` value.'
|
420
460
|
Enabled: 'pending'
|
@@ -423,6 +463,12 @@ Rails/I18nLocaleAssignment:
|
|
423
463
|
- spec/**/*.rb
|
424
464
|
- test/**/*.rb
|
425
465
|
|
466
|
+
Rails/I18nLocaleTexts:
|
467
|
+
Description: 'Enforces use of I18n and locale files instead of locale specific strings.'
|
468
|
+
StyleGuide: 'https://rails.rubystyle.guide/#locale-texts'
|
469
|
+
Enabled: pending
|
470
|
+
VersionAdded: '2.14'
|
471
|
+
|
426
472
|
Rails/IgnoredSkipActionFilterOption:
|
427
473
|
Description: 'Checks that `if` and `only` (or `except`) are not used together as options of `skip_*` action filter.'
|
428
474
|
Reference: 'https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options'
|
@@ -495,6 +541,13 @@ Rails/MatchRoute:
|
|
495
541
|
- config/routes.rb
|
496
542
|
- config/routes/**/*.rb
|
497
543
|
|
544
|
+
Rails/MigrationClassName:
|
545
|
+
Description: 'The class name of the migration should match its file name.'
|
546
|
+
Enabled: pending
|
547
|
+
VersionAdded: '2.14'
|
548
|
+
Include:
|
549
|
+
- db/migrate/*.rb
|
550
|
+
|
498
551
|
Rails/NegateInclude:
|
499
552
|
Description: 'Prefer `collection.exclude?(obj)` over `!collection.include?(obj)`.'
|
500
553
|
StyleGuide: 'https://rails.rubystyle.guide#exclude'
|
@@ -817,6 +870,15 @@ Rails/SquishedSQLHeredocs:
|
|
817
870
|
# to be preserved in order to work, thus auto-correction is not safe.
|
818
871
|
SafeAutoCorrect: false
|
819
872
|
|
873
|
+
Rails/TableNameAssignment:
|
874
|
+
Description: >-
|
875
|
+
Do not use `self.table_name =`. Use Inflections or `table_name_prefix` instead.
|
876
|
+
StyleGuide: 'https://rails.rubystyle.guide/#keep-ar-defaults'
|
877
|
+
Enabled: false
|
878
|
+
VersionAdded: '2.14'
|
879
|
+
Include:
|
880
|
+
- app/models/**/*.rb
|
881
|
+
|
820
882
|
Rails/TimeZone:
|
821
883
|
Description: 'Checks the correct usage of time zone aware methods.'
|
822
884
|
StyleGuide: 'https://rails.rubystyle.guide#time'
|
@@ -843,6 +905,11 @@ Rails/TimeZoneAssignment:
|
|
843
905
|
- spec/**/*.rb
|
844
906
|
- test/**/*.rb
|
845
907
|
|
908
|
+
Rails/TransactionExitStatement:
|
909
|
+
Description: 'Avoid the usage of `return`, `break` and `throw` in transaction blocks.'
|
910
|
+
Enabled: pending
|
911
|
+
VersionAdded: '2.14'
|
912
|
+
|
846
913
|
Rails/UniqBeforePluck:
|
847
914
|
Description: 'Prefer the use of uniq or distinct before pluck.'
|
848
915
|
Enabled: true
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# A mixin to return all of the class send nodes.
|
6
|
+
module ClassSendNodeHelper
|
7
|
+
def class_send_nodes(class_node)
|
8
|
+
class_def = class_node.body
|
9
|
+
|
10
|
+
return [] unless class_def
|
11
|
+
|
12
|
+
if class_def.send_type?
|
13
|
+
[class_def]
|
14
|
+
else
|
15
|
+
class_def.each_child_node(:send)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Using `ActionController::TestCase`` is discouraged and should be replaced by
|
7
|
+
# `ActionDispatch::IntegrationTest``. Controller tests are too close to the
|
8
|
+
# internals of a controller whereas integration tests mimic the browser/user.
|
9
|
+
#
|
10
|
+
# @safety
|
11
|
+
# This cop's autocorrection is unsafe because the API of each test case class is different.
|
12
|
+
# Make sure to update each test of your controller test cases after changing the superclass.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # bad
|
16
|
+
# class MyControllerTest < ActionController::TestCase
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# class MyControllerTest < ActionDispatch::IntegrationTest
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
class ActionControllerTestCase < Base
|
24
|
+
extend AutoCorrector
|
25
|
+
extend TargetRailsVersion
|
26
|
+
|
27
|
+
MSG = 'Use `ActionDispatch::IntegrationTest` instead.'
|
28
|
+
|
29
|
+
minimum_target_rails_version 5.0
|
30
|
+
|
31
|
+
def_node_matcher :action_controller_test_case?, <<~PATTERN
|
32
|
+
(class
|
33
|
+
(const nil? _)
|
34
|
+
(const (const {nil? cbase} :ActionController) :TestCase) nil?)
|
35
|
+
PATTERN
|
36
|
+
|
37
|
+
def on_class(node)
|
38
|
+
return unless action_controller_test_case?(node)
|
39
|
+
|
40
|
+
add_offense(node.parent_class) do |corrector|
|
41
|
+
corrector.replace(node.parent_class, 'ActionDispatch::IntegrationTest')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -32,6 +32,8 @@ module RuboCop
|
|
32
32
|
# after_update_commit :log_update_action
|
33
33
|
#
|
34
34
|
class AfterCommitOverride < Base
|
35
|
+
include ClassSendNodeHelper
|
36
|
+
|
35
37
|
MSG = 'There can only be one `after_*_commit :%<name>s` hook defined for a model.'
|
36
38
|
|
37
39
|
AFTER_COMMIT_CALLBACKS = %i[
|
@@ -63,18 +65,6 @@ module RuboCop
|
|
63
65
|
end
|
64
66
|
end
|
65
67
|
|
66
|
-
def class_send_nodes(class_node)
|
67
|
-
class_def = class_node.body
|
68
|
-
|
69
|
-
return [] unless class_def
|
70
|
-
|
71
|
-
if class_def.send_type?
|
72
|
-
[class_def]
|
73
|
-
else
|
74
|
-
class_def.each_child_node(:send).to_a
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
68
|
def after_commit_callback?(node)
|
79
69
|
AFTER_COMMIT_CALLBACKS.include?(node.method_name)
|
80
70
|
end
|
@@ -155,17 +155,31 @@ module RuboCop
|
|
155
155
|
return if include_bulk_options?(node)
|
156
156
|
return unless node.block_node
|
157
157
|
|
158
|
-
send_nodes = node.block_node.body
|
158
|
+
send_nodes = send_nodes_from_change_table_block(node.block_node.body)
|
159
159
|
|
160
|
-
|
161
|
-
combinable_transformations.include?(send_node.method_name)
|
162
|
-
end
|
163
|
-
|
164
|
-
add_offense_for_change_table(node) if transformations.size > 1
|
160
|
+
add_offense_for_change_table(node) if count_transformations(send_nodes) > 1
|
165
161
|
end
|
166
162
|
|
167
163
|
private
|
168
164
|
|
165
|
+
def send_nodes_from_change_table_block(body)
|
166
|
+
if body.send_type?
|
167
|
+
[body]
|
168
|
+
else
|
169
|
+
body.each_child_node(:send).to_a
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def count_transformations(send_nodes)
|
174
|
+
send_nodes.sum do |node|
|
175
|
+
if node.method?(:remove)
|
176
|
+
node.arguments.count { |arg| !arg.hash_type? }
|
177
|
+
else
|
178
|
+
combinable_transformations.include?(node.method_name) ? 1 : 0
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
169
183
|
# @param node [RuboCop::AST::SendNode] (send nil? :change_table ...)
|
170
184
|
def include_bulk_options?(node)
|
171
185
|
# arguments: [{(sym :table)(str "table")} (hash (pair (sym :bulk) _))]
|
@@ -13,6 +13,12 @@ module RuboCop
|
|
13
13
|
# `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `blank?`.
|
14
14
|
# This will work fine when the receiver is a hash object.
|
15
15
|
#
|
16
|
+
# And `compact_blank!` has different implementations for `Array`, `Hash`, and
|
17
|
+
# `ActionController::Parameters`.
|
18
|
+
# `Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`.
|
19
|
+
# `ActionController::Parameters#compact_blank!` is equivalent to `reject!(&:blank?)`.
|
20
|
+
# If the cop makes a mistake, auto-corrected code may get unexpected behavior.
|
21
|
+
#
|
16
22
|
# @example
|
17
23
|
#
|
18
24
|
# # bad
|
@@ -23,8 +29,10 @@ module RuboCop
|
|
23
29
|
# collection.compact_blank
|
24
30
|
#
|
25
31
|
# # bad
|
26
|
-
# collection.
|
27
|
-
# collection.
|
32
|
+
# collection.delete_if(&:blank?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
33
|
+
# collection.delete_if { |_k, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
34
|
+
# collection.reject!(&:blank?) # Same behavior as `ActionController::Parameters#compact_blank!`
|
35
|
+
# collection.reject! { |_k, v| v.blank? } # Same behavior as `ActionController::Parameters#compact_blank!`
|
28
36
|
#
|
29
37
|
# # good
|
30
38
|
# collection.compact_blank!
|
@@ -35,20 +43,20 @@ module RuboCop
|
|
35
43
|
extend TargetRailsVersion
|
36
44
|
|
37
45
|
MSG = 'Use `%<preferred_method>s` instead.'
|
38
|
-
RESTRICT_ON_SEND = %i[reject reject!].freeze
|
46
|
+
RESTRICT_ON_SEND = %i[reject delete_if reject!].freeze
|
39
47
|
|
40
48
|
minimum_target_rails_version 6.1
|
41
49
|
|
42
50
|
def_node_matcher :reject_with_block?, <<~PATTERN
|
43
51
|
(block
|
44
|
-
(send _ {:reject :reject!})
|
52
|
+
(send _ {:reject :delete_if :reject!})
|
45
53
|
$(args ...)
|
46
54
|
(send
|
47
55
|
$(lvar _) :blank?))
|
48
56
|
PATTERN
|
49
57
|
|
50
58
|
def_node_matcher :reject_with_block_pass?, <<~PATTERN
|
51
|
-
(send _ {:reject :reject!}
|
59
|
+
(send _ {:reject :delete_if :reject!}
|
52
60
|
(block_pass
|
53
61
|
(sym :blank?)))
|
54
62
|
PATTERN
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks direct manipulation of ActiveModel#errors as hash.
|
7
|
+
# These operations are deprecated in Rails 6.1 and will not work in Rails 7.
|
8
|
+
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe because it can report `errors` manipulation on non-ActiveModel,
|
11
|
+
# which is obviously valid.
|
12
|
+
# The cop has no way of knowing whether a variable is an ActiveModel or not.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # bad
|
16
|
+
# user.errors[:name] << 'msg'
|
17
|
+
# user.errors.messages[:name] << 'msg'
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# user.errors.add(:name, 'msg')
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# user.errors[:name].clear
|
24
|
+
# user.errors.messages[:name].clear
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# user.errors.delete(:name)
|
28
|
+
#
|
29
|
+
class DeprecatedActiveModelErrorsMethods < Base
|
30
|
+
MSG = 'Avoid manipulating ActiveModel errors as hash directly.'
|
31
|
+
|
32
|
+
MANIPULATIVE_METHODS = Set[
|
33
|
+
*%i[
|
34
|
+
<< append clear collect! compact! concat
|
35
|
+
delete delete_at delete_if drop drop_while fill filter! keep_if
|
36
|
+
flatten! insert map! pop prepend push reject! replace reverse!
|
37
|
+
rotate! select! shift shuffle! slice! sort! sort_by! uniq! unshift
|
38
|
+
]
|
39
|
+
].freeze
|
40
|
+
|
41
|
+
def_node_matcher :receiver_matcher_outside_model, '{send ivar lvar}'
|
42
|
+
def_node_matcher :receiver_matcher_inside_model, '{nil? send ivar lvar}'
|
43
|
+
|
44
|
+
def_node_matcher :any_manipulation?, <<~PATTERN
|
45
|
+
{
|
46
|
+
#root_manipulation?
|
47
|
+
#root_assignment?
|
48
|
+
#messages_details_manipulation?
|
49
|
+
#messages_details_assignment?
|
50
|
+
}
|
51
|
+
PATTERN
|
52
|
+
|
53
|
+
def_node_matcher :root_manipulation?, <<~PATTERN
|
54
|
+
(send
|
55
|
+
(send
|
56
|
+
(send #receiver_matcher :errors) :[] ...)
|
57
|
+
MANIPULATIVE_METHODS
|
58
|
+
...
|
59
|
+
)
|
60
|
+
PATTERN
|
61
|
+
|
62
|
+
def_node_matcher :root_assignment?, <<~PATTERN
|
63
|
+
(send
|
64
|
+
(send #receiver_matcher :errors)
|
65
|
+
:[]=
|
66
|
+
...)
|
67
|
+
PATTERN
|
68
|
+
|
69
|
+
def_node_matcher :messages_details_manipulation?, <<~PATTERN
|
70
|
+
(send
|
71
|
+
(send
|
72
|
+
(send
|
73
|
+
(send #receiver_matcher :errors)
|
74
|
+
{:messages :details})
|
75
|
+
:[]
|
76
|
+
...)
|
77
|
+
MANIPULATIVE_METHODS
|
78
|
+
...)
|
79
|
+
PATTERN
|
80
|
+
|
81
|
+
def_node_matcher :messages_details_assignment?, <<~PATTERN
|
82
|
+
(send
|
83
|
+
(send
|
84
|
+
(send #receiver_matcher :errors)
|
85
|
+
{:messages :details})
|
86
|
+
:[]=
|
87
|
+
...)
|
88
|
+
PATTERN
|
89
|
+
|
90
|
+
def on_send(node)
|
91
|
+
any_manipulation?(node) do
|
92
|
+
add_offense(node)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def receiver_matcher(node)
|
99
|
+
model_file? ? receiver_matcher_inside_model(node) : receiver_matcher_outside_model(node)
|
100
|
+
end
|
101
|
+
|
102
|
+
def model_file?
|
103
|
+
processed_source.buffer.name.include?('/models/')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for associations that have been defined multiple times in the same file.
|
7
|
+
#
|
8
|
+
# When an association is defined multiple times on a model, Active Record overrides the
|
9
|
+
# previously defined association with the new one. Because of this, this cop's autocorrection
|
10
|
+
# simply keeps the last of any duplicates and discards the rest.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# belongs_to :foo
|
16
|
+
# belongs_to :bar
|
17
|
+
# has_one :foo
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# belongs_to :bar
|
21
|
+
# has_one :foo
|
22
|
+
#
|
23
|
+
class DuplicateAssociation < Base
|
24
|
+
include RangeHelp
|
25
|
+
extend AutoCorrector
|
26
|
+
include ClassSendNodeHelper
|
27
|
+
|
28
|
+
MSG = "Association `%<name>s` is defined multiple times. Don't repeat associations."
|
29
|
+
|
30
|
+
def_node_matcher :association, <<~PATTERN
|
31
|
+
(send nil? {:belongs_to :has_one :has_many :has_and_belongs_to_many} ({sym str} $_) ...)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_class(class_node)
|
35
|
+
offenses(class_node).each do |name, nodes|
|
36
|
+
nodes.each do |node|
|
37
|
+
add_offense(node, message: format(MSG, name: name)) do |corrector|
|
38
|
+
next if nodes.last == node
|
39
|
+
|
40
|
+
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def offenses(class_node)
|
49
|
+
class_send_nodes(class_node).select { |node| association(node) }
|
50
|
+
.group_by { |node| association(node).to_sym }
|
51
|
+
.select { |_, nodes| nodes.length > 1 }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks for multiple scopes in a model that have the same `where` clause. This
|
7
|
+
# often means you copy/pasted a scope, updated the name, and forgot to change the condition.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# scope :visible, -> { where(visible: true) }
|
13
|
+
# scope :hidden, -> { where(visible: true) }
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# scope :visible, -> { where(visible: true) }
|
17
|
+
# scope :hidden, -> { where(visible: false) }
|
18
|
+
#
|
19
|
+
class DuplicateScope < Base
|
20
|
+
include ClassSendNodeHelper
|
21
|
+
|
22
|
+
MSG = 'Multiple scopes share this same where clause.'
|
23
|
+
|
24
|
+
def_node_matcher :scope, <<~PATTERN
|
25
|
+
(send nil? :scope _ $...)
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def on_class(class_node)
|
29
|
+
offenses(class_node).each do |node|
|
30
|
+
add_offense(node)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def offenses(class_node)
|
37
|
+
class_send_nodes(class_node).select { |node| scope(node) }
|
38
|
+
.group_by { |node| scope(node) }
|
39
|
+
.select { |_, nodes| nodes.length > 1 }
|
40
|
+
.values
|
41
|
+
.flatten
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks for places where I18n "lazy" lookup can be used.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # en.yml
|
10
|
+
# # en:
|
11
|
+
# # books:
|
12
|
+
# # create:
|
13
|
+
# # success: Book created!
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# class BooksController < ApplicationController
|
17
|
+
# def create
|
18
|
+
# # ...
|
19
|
+
# redirect_to books_url, notice: t('books.create.success')
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# class BooksController < ApplicationController
|
25
|
+
# def create
|
26
|
+
# # ...
|
27
|
+
# redirect_to books_url, notice: t('.success')
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
class I18nLazyLookup < Base
|
32
|
+
include VisibilityHelp
|
33
|
+
extend AutoCorrector
|
34
|
+
|
35
|
+
MSG = 'Use "lazy" lookup for the text used in controllers.'
|
36
|
+
|
37
|
+
def_node_matcher :translate_call?, <<~PATTERN
|
38
|
+
(send nil? {:translate :t} ${sym_type? str_type?} ...)
|
39
|
+
PATTERN
|
40
|
+
|
41
|
+
def on_send(node)
|
42
|
+
translate_call?(node) do |key_node|
|
43
|
+
key = key_node.value
|
44
|
+
return if key.to_s.start_with?('.')
|
45
|
+
|
46
|
+
controller, action = controller_and_action(node)
|
47
|
+
return unless controller && action
|
48
|
+
|
49
|
+
scoped_key = get_scoped_key(key_node, controller, action)
|
50
|
+
return unless key == scoped_key
|
51
|
+
|
52
|
+
add_offense(key_node) do |corrector|
|
53
|
+
unscoped_key = key_node.value.to_s.split('.').last
|
54
|
+
corrector.replace(key_node, "'.#{unscoped_key}'")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def controller_and_action(node)
|
62
|
+
action_node = node.each_ancestor(:def).first
|
63
|
+
return unless action_node && node_visibility(action_node) == :public
|
64
|
+
|
65
|
+
controller_node = node.each_ancestor(:class).first
|
66
|
+
return unless controller_node && controller_node.identifier.source.end_with?('Controller')
|
67
|
+
|
68
|
+
[controller_node, action_node]
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_scoped_key(key_node, controller, action)
|
72
|
+
path = controller_path(controller).tr('/', '.')
|
73
|
+
action_name = action.method_name
|
74
|
+
key = key_node.value.to_s.split('.').last
|
75
|
+
|
76
|
+
"#{path}.#{action_name}.#{key}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def controller_path(controller)
|
80
|
+
module_name = controller.parent_module_name
|
81
|
+
controller_name = controller.identifier.source
|
82
|
+
|
83
|
+
path = if module_name == 'Object'
|
84
|
+
controller_name
|
85
|
+
else
|
86
|
+
"#{module_name}::#{controller_name}"
|
87
|
+
end
|
88
|
+
|
89
|
+
path.delete_suffix('Controller').underscore
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Enforces use of I18n and locale files instead of locale specific strings.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# class User < ApplicationRecord
|
11
|
+
# validates :email, presence: { message: "must be present" }
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# # config/locales/en.yml
|
16
|
+
# # en:
|
17
|
+
# # activerecord:
|
18
|
+
# # errors:
|
19
|
+
# # models:
|
20
|
+
# # user:
|
21
|
+
# # blank: "must be present"
|
22
|
+
#
|
23
|
+
# class User < ApplicationRecord
|
24
|
+
# validates :email, presence: true
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # bad
|
28
|
+
# class PostsController < ApplicationController
|
29
|
+
# def create
|
30
|
+
# # ...
|
31
|
+
# redirect_to root_path, notice: "Post created!"
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# # config/locales/en.yml
|
37
|
+
# # en:
|
38
|
+
# # posts:
|
39
|
+
# # create:
|
40
|
+
# # success: "Post created!"
|
41
|
+
#
|
42
|
+
# class PostsController < ApplicationController
|
43
|
+
# def create
|
44
|
+
# # ...
|
45
|
+
# redirect_to root_path, notice: t(".success")
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# # bad
|
50
|
+
# class UserMailer < ApplicationMailer
|
51
|
+
# def welcome(user)
|
52
|
+
# mail(to: user.email, subject: "Welcome to My Awesome Site")
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# # good
|
57
|
+
# # config/locales/en.yml
|
58
|
+
# # en:
|
59
|
+
# # user_mailer:
|
60
|
+
# # welcome:
|
61
|
+
# # subject: "Welcome to My Awesome Site"
|
62
|
+
#
|
63
|
+
# class UserMailer < ApplicationMailer
|
64
|
+
# def welcome(user)
|
65
|
+
# mail(to: user.email)
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
class I18nLocaleTexts < Base
|
70
|
+
MSG = 'Move locale texts to the locale files in the `config/locales` directory.'
|
71
|
+
|
72
|
+
RESTRICT_ON_SEND = %i[validates redirect_to []= mail].freeze
|
73
|
+
|
74
|
+
def_node_search :validation_message, <<~PATTERN
|
75
|
+
(pair (sym :message) $str)
|
76
|
+
PATTERN
|
77
|
+
|
78
|
+
def_node_search :redirect_to_flash, <<~PATTERN
|
79
|
+
(pair (sym {:notice :alert}) $str)
|
80
|
+
PATTERN
|
81
|
+
|
82
|
+
def_node_matcher :flash_assignment?, <<~PATTERN
|
83
|
+
(send (send nil? :flash) :[]= _ $str)
|
84
|
+
PATTERN
|
85
|
+
|
86
|
+
def_node_search :mail_subject, <<~PATTERN
|
87
|
+
(pair (sym :subject) $str)
|
88
|
+
PATTERN
|
89
|
+
|
90
|
+
def on_send(node)
|
91
|
+
case node.method_name
|
92
|
+
when :validates
|
93
|
+
validation_message(node) do |text_node|
|
94
|
+
add_offense(text_node)
|
95
|
+
end
|
96
|
+
return
|
97
|
+
when :redirect_to
|
98
|
+
text_node = redirect_to_flash(node).to_a.last
|
99
|
+
when :[]=
|
100
|
+
text_node = flash_assignment?(node)
|
101
|
+
when :mail
|
102
|
+
text_node = mail_subject(node).to_a.last
|
103
|
+
end
|
104
|
+
|
105
|
+
add_offense(text_node) if text_node
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop makes sure that each migration file defines a migration class
|
7
|
+
# whose name matches the file name.
|
8
|
+
# (e.g. `20220224111111_create_users.rb` should define `CreateUsers` class.)
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # db/migrate/20220224111111_create_users.rb
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# class SellBooks < ActiveRecord::Migration[7.0]
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# class CreateUsers < ActiveRecord::Migration[7.0]
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
class MigrationClassName < Base
|
22
|
+
extend AutoCorrector
|
23
|
+
include MigrationsHelper
|
24
|
+
|
25
|
+
MSG = 'Replace with `%<camelized_basename>s` that matches the file name.'
|
26
|
+
|
27
|
+
def on_class(node)
|
28
|
+
return unless migration_class?(node)
|
29
|
+
|
30
|
+
basename = basename_without_timestamp_and_suffix(processed_source.file_path)
|
31
|
+
|
32
|
+
class_identifier = node.identifier
|
33
|
+
camelized_basename = camelize(basename)
|
34
|
+
return if class_identifier.source.casecmp(camelized_basename).zero?
|
35
|
+
|
36
|
+
message = format(MSG, camelized_basename: camelized_basename)
|
37
|
+
|
38
|
+
add_offense(class_identifier, message: message) do |corrector|
|
39
|
+
corrector.replace(class_identifier, camelized_basename)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def basename_without_timestamp_and_suffix(filepath)
|
46
|
+
basename = File.basename(filepath, '.rb')
|
47
|
+
basename = remove_gem_suffix(basename)
|
48
|
+
|
49
|
+
basename.sub(/\A\d+_/, '')
|
50
|
+
end
|
51
|
+
|
52
|
+
# e.g.: from `add_blobs.active_storage` to `add_blobs`.
|
53
|
+
def remove_gem_suffix(file_name)
|
54
|
+
file_name.sub(/\..+\z/, '')
|
55
|
+
end
|
56
|
+
|
57
|
+
def camelize(word)
|
58
|
+
word.split('_').map(&:capitalize).join
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -21,25 +21,31 @@ module RuboCop
|
|
21
21
|
extend AutoCorrector
|
22
22
|
extend TargetRailsVersion
|
23
23
|
|
24
|
-
MSG = 'Prefer `pluck(:%<value>s)` over `%<
|
24
|
+
MSG = 'Prefer `pluck(:%<value>s)` over `%<current>s`.'
|
25
25
|
|
26
26
|
minimum_target_rails_version 5.0
|
27
27
|
|
28
28
|
def_node_matcher :pluck_candidate?, <<~PATTERN
|
29
|
-
(block (send _
|
29
|
+
({block numblock} (send _ {:map :collect}) $_argument (send (lvar $_element) :[] (sym $_value)))
|
30
30
|
PATTERN
|
31
31
|
|
32
32
|
def on_block(node)
|
33
|
-
pluck_candidate?(node) do |
|
34
|
-
|
33
|
+
pluck_candidate?(node) do |argument, element, value|
|
34
|
+
match = if node.block_type?
|
35
|
+
argument.children.first.source.to_sym == element
|
36
|
+
else # numblock
|
37
|
+
argument == 1 && element == :_1
|
38
|
+
end
|
39
|
+
next unless match
|
35
40
|
|
36
|
-
message = message(
|
41
|
+
message = message(value, node)
|
37
42
|
|
38
43
|
add_offense(offense_range(node), message: message) do |corrector|
|
39
44
|
corrector.replace(offense_range(node), "pluck(:#{value})")
|
40
45
|
end
|
41
46
|
end
|
42
47
|
end
|
48
|
+
alias on_numblock on_block
|
43
49
|
|
44
50
|
private
|
45
51
|
|
@@ -47,8 +53,10 @@ module RuboCop
|
|
47
53
|
node.send_node.loc.selector.join(node.loc.end)
|
48
54
|
end
|
49
55
|
|
50
|
-
def message(
|
51
|
-
|
56
|
+
def message(value, node)
|
57
|
+
current = offense_range(node).source
|
58
|
+
|
59
|
+
format(MSG, value: value, current: current)
|
52
60
|
end
|
53
61
|
end
|
54
62
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop enforces the absence of explicit table name assignment.
|
7
|
+
#
|
8
|
+
# `self.table_name=` should only be used for very good reasons,
|
9
|
+
# such as not having control over the database, or working
|
10
|
+
# on a legacy project.
|
11
|
+
#
|
12
|
+
# If you need to change how your model's name is translated to
|
13
|
+
# a table name, you may want to look at Inflections:
|
14
|
+
# https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html
|
15
|
+
#
|
16
|
+
# If you wish to add a prefix in front of your model, or wish to change
|
17
|
+
# the default prefix, `self.table_name_prefix` might better suit your needs:
|
18
|
+
# https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema.html#method-c-table_name_prefix-3D
|
19
|
+
#
|
20
|
+
# STI base classes named `Base` are ignored by this cop.
|
21
|
+
# For more information: https://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# # bad
|
25
|
+
# self.table_name = 'some_table_name'
|
26
|
+
# self.table_name = :some_other_name
|
27
|
+
class TableNameAssignment < Base
|
28
|
+
include ActiveRecordHelper
|
29
|
+
|
30
|
+
MSG = 'Do not use `self.table_name =`.'
|
31
|
+
|
32
|
+
def_node_matcher :base_class?, <<~PATTERN
|
33
|
+
(class (const ... :Base) ...)
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def on_class(class_node)
|
37
|
+
return if base_class?(class_node)
|
38
|
+
|
39
|
+
find_set_table_name(class_node).each { |node| add_offense(node) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks for the use of exit statements (namely `return`,
|
7
|
+
# `break` and `throw`) in transactions. This is due to the eventual
|
8
|
+
# unexpected behavior when using ActiveRecord >= 7, where transactions
|
9
|
+
# exitted using these statements are being rollbacked rather than
|
10
|
+
# committed (pre ActiveRecord 7 behavior).
|
11
|
+
#
|
12
|
+
# As alternatives, it would be more intuitive to explicitly raise an
|
13
|
+
# error when rollback is desired, and to use `next` when commit is
|
14
|
+
# desired.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# # bad
|
18
|
+
# ApplicationRecord.transaction do
|
19
|
+
# return if user.active?
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# ApplicationRecord.transaction do
|
24
|
+
# break if user.active?
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # bad
|
28
|
+
# ApplicationRecord.transaction do
|
29
|
+
# throw if user.active?
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# ApplicationRecord.transaction do
|
34
|
+
# # Rollback
|
35
|
+
# raise "User is active" if user.active?
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# # good
|
39
|
+
# ApplicationRecord.transaction do
|
40
|
+
# # Commit
|
41
|
+
# next if user.active?
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# @see https://github.com/rails/rails/commit/15aa4200e083
|
45
|
+
class TransactionExitStatement < Base
|
46
|
+
MSG = <<~MSG.chomp
|
47
|
+
Exit statement `%<statement>s` is not allowed. Use `raise` (rollback) or `next` (commit).
|
48
|
+
MSG
|
49
|
+
|
50
|
+
RESTRICT_ON_SEND = %i[transaction].freeze
|
51
|
+
|
52
|
+
def_node_search :exit_statements, <<~PATTERN
|
53
|
+
({return | break | send nil? :throw} ...)
|
54
|
+
PATTERN
|
55
|
+
|
56
|
+
def on_send(node)
|
57
|
+
return unless (parent = node.parent)
|
58
|
+
return unless parent.block_type? && parent.body
|
59
|
+
|
60
|
+
exit_statements(parent.body).each do |statement_node|
|
61
|
+
next if in_rescue?(statement_node) || nested_block?(statement_node)
|
62
|
+
|
63
|
+
statement = statement(statement_node)
|
64
|
+
message = format(MSG, statement: statement)
|
65
|
+
|
66
|
+
add_offense(statement_node, message: message)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def statement(statement_node)
|
73
|
+
if statement_node.return_type?
|
74
|
+
'return'
|
75
|
+
elsif statement_node.break_type?
|
76
|
+
'break'
|
77
|
+
else
|
78
|
+
statement_node.method_name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def in_rescue?(statement_node)
|
83
|
+
statement_node.ancestors.find(&:rescue_type?)
|
84
|
+
end
|
85
|
+
|
86
|
+
def nested_block?(statement_node)
|
87
|
+
return false unless statement_node.break_type?
|
88
|
+
|
89
|
+
!statement_node.ancestors.find(&:block_type?).method?(:transaction)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
require_relative 'mixin/active_record_helper'
|
4
4
|
require_relative 'mixin/active_record_migrations_helper'
|
5
|
+
require_relative 'mixin/class_send_node_helper'
|
5
6
|
require_relative 'mixin/enforce_superclass'
|
6
7
|
require_relative 'mixin/index_method'
|
7
8
|
require_relative 'mixin/migrations_helper'
|
8
9
|
require_relative 'mixin/target_rails_version'
|
9
10
|
|
11
|
+
require_relative 'rails/action_controller_test_case'
|
10
12
|
require_relative 'rails/action_filter'
|
11
13
|
require_relative 'rails/active_record_aliases'
|
12
14
|
require_relative 'rails/active_record_callbacks_order'
|
@@ -31,6 +33,9 @@ require_relative 'rails/date'
|
|
31
33
|
require_relative 'rails/default_scope'
|
32
34
|
require_relative 'rails/delegate'
|
33
35
|
require_relative 'rails/delegate_allow_blank'
|
36
|
+
require_relative 'rails/deprecated_active_model_errors_methods'
|
37
|
+
require_relative 'rails/duplicate_association'
|
38
|
+
require_relative 'rails/duplicate_scope'
|
34
39
|
require_relative 'rails/duration_arithmetic'
|
35
40
|
require_relative 'rails/dynamic_find_by'
|
36
41
|
require_relative 'rails/eager_evaluation_log_message'
|
@@ -49,7 +54,9 @@ require_relative 'rails/has_many_or_has_one_dependent'
|
|
49
54
|
require_relative 'rails/helper_instance_variable'
|
50
55
|
require_relative 'rails/http_positional_arguments'
|
51
56
|
require_relative 'rails/http_status'
|
57
|
+
require_relative 'rails/i18n_lazy_lookup'
|
52
58
|
require_relative 'rails/i18n_locale_assignment'
|
59
|
+
require_relative 'rails/i18n_locale_texts'
|
53
60
|
require_relative 'rails/ignored_skip_action_filter_option'
|
54
61
|
require_relative 'rails/index_by'
|
55
62
|
require_relative 'rails/index_with'
|
@@ -59,6 +66,7 @@ require_relative 'rails/lexically_scoped_action_filter'
|
|
59
66
|
require_relative 'rails/link_to_blank'
|
60
67
|
require_relative 'rails/mailer_name'
|
61
68
|
require_relative 'rails/match_route'
|
69
|
+
require_relative 'rails/migration_class_name'
|
62
70
|
require_relative 'rails/negate_include'
|
63
71
|
require_relative 'rails/not_null_column'
|
64
72
|
require_relative 'rails/order_by_id'
|
@@ -96,8 +104,10 @@ require_relative 'rails/scope_args'
|
|
96
104
|
require_relative 'rails/short_i18n'
|
97
105
|
require_relative 'rails/skips_model_validations'
|
98
106
|
require_relative 'rails/squished_sql_heredocs'
|
107
|
+
require_relative 'rails/table_name_assignment'
|
99
108
|
require_relative 'rails/time_zone'
|
100
109
|
require_relative 'rails/time_zone_assignment'
|
110
|
+
require_relative 'rails/transaction_exit_statement'
|
101
111
|
require_relative 'rails/uniq_before_pluck'
|
102
112
|
require_relative 'rails/unique_validation_without_index'
|
103
113
|
require_relative 'rails/unknown_env'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.14.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-03-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -79,10 +79,12 @@ files:
|
|
79
79
|
- lib/rubocop-rails.rb
|
80
80
|
- lib/rubocop/cop/mixin/active_record_helper.rb
|
81
81
|
- lib/rubocop/cop/mixin/active_record_migrations_helper.rb
|
82
|
+
- lib/rubocop/cop/mixin/class_send_node_helper.rb
|
82
83
|
- lib/rubocop/cop/mixin/enforce_superclass.rb
|
83
84
|
- lib/rubocop/cop/mixin/index_method.rb
|
84
85
|
- lib/rubocop/cop/mixin/migrations_helper.rb
|
85
86
|
- lib/rubocop/cop/mixin/target_rails_version.rb
|
87
|
+
- lib/rubocop/cop/rails/action_controller_test_case.rb
|
86
88
|
- lib/rubocop/cop/rails/action_filter.rb
|
87
89
|
- lib/rubocop/cop/rails/active_record_aliases.rb
|
88
90
|
- lib/rubocop/cop/rails/active_record_callbacks_order.rb
|
@@ -107,6 +109,9 @@ files:
|
|
107
109
|
- lib/rubocop/cop/rails/default_scope.rb
|
108
110
|
- lib/rubocop/cop/rails/delegate.rb
|
109
111
|
- lib/rubocop/cop/rails/delegate_allow_blank.rb
|
112
|
+
- lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb
|
113
|
+
- lib/rubocop/cop/rails/duplicate_association.rb
|
114
|
+
- lib/rubocop/cop/rails/duplicate_scope.rb
|
110
115
|
- lib/rubocop/cop/rails/duration_arithmetic.rb
|
111
116
|
- lib/rubocop/cop/rails/dynamic_find_by.rb
|
112
117
|
- lib/rubocop/cop/rails/eager_evaluation_log_message.rb
|
@@ -125,7 +130,9 @@ files:
|
|
125
130
|
- lib/rubocop/cop/rails/helper_instance_variable.rb
|
126
131
|
- lib/rubocop/cop/rails/http_positional_arguments.rb
|
127
132
|
- lib/rubocop/cop/rails/http_status.rb
|
133
|
+
- lib/rubocop/cop/rails/i18n_lazy_lookup.rb
|
128
134
|
- lib/rubocop/cop/rails/i18n_locale_assignment.rb
|
135
|
+
- lib/rubocop/cop/rails/i18n_locale_texts.rb
|
129
136
|
- lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb
|
130
137
|
- lib/rubocop/cop/rails/index_by.rb
|
131
138
|
- lib/rubocop/cop/rails/index_with.rb
|
@@ -135,6 +142,7 @@ files:
|
|
135
142
|
- lib/rubocop/cop/rails/link_to_blank.rb
|
136
143
|
- lib/rubocop/cop/rails/mailer_name.rb
|
137
144
|
- lib/rubocop/cop/rails/match_route.rb
|
145
|
+
- lib/rubocop/cop/rails/migration_class_name.rb
|
138
146
|
- lib/rubocop/cop/rails/negate_include.rb
|
139
147
|
- lib/rubocop/cop/rails/not_null_column.rb
|
140
148
|
- lib/rubocop/cop/rails/order_by_id.rb
|
@@ -172,8 +180,10 @@ files:
|
|
172
180
|
- lib/rubocop/cop/rails/short_i18n.rb
|
173
181
|
- lib/rubocop/cop/rails/skips_model_validations.rb
|
174
182
|
- lib/rubocop/cop/rails/squished_sql_heredocs.rb
|
183
|
+
- lib/rubocop/cop/rails/table_name_assignment.rb
|
175
184
|
- lib/rubocop/cop/rails/time_zone.rb
|
176
185
|
- lib/rubocop/cop/rails/time_zone_assignment.rb
|
186
|
+
- lib/rubocop/cop/rails/transaction_exit_statement.rb
|
177
187
|
- lib/rubocop/cop/rails/uniq_before_pluck.rb
|
178
188
|
- lib/rubocop/cop/rails/unique_validation_without_index.rb
|
179
189
|
- lib/rubocop/cop/rails/unknown_env.rb
|
@@ -195,7 +205,7 @@ metadata:
|
|
195
205
|
homepage_uri: https://docs.rubocop.org/rubocop-rails/
|
196
206
|
changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
|
197
207
|
source_code_uri: https://github.com/rubocop/rubocop-rails/
|
198
|
-
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.
|
208
|
+
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.14/
|
199
209
|
bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
|
200
210
|
rubygems_mfa_required: 'true'
|
201
211
|
post_install_message:
|