rubocop-rails 2.15.2 → 2.17.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 +120 -0
- data/config/obsoletion.yml +10 -0
- data/lib/rubocop/cop/mixin/active_record_helper.rb +1 -4
- data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +1 -3
- data/lib/rubocop/cop/mixin/index_method.rb +5 -15
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +99 -0
- data/lib/rubocop/cop/rails/action_controller_test_case.rb +1 -1
- data/lib/rubocop/cop/rails/action_filter.rb +1 -1
- data/lib/rubocop/cop/rails/action_order.rb +81 -0
- data/lib/rubocop/cop/rails/active_record_aliases.rb +1 -4
- data/lib/rubocop/cop/rails/active_record_override.rb +2 -5
- data/lib/rubocop/cop/rails/active_support_on_load.rb +70 -0
- data/lib/rubocop/cop/rails/add_column_index.rb +1 -4
- data/lib/rubocop/cop/rails/blank.rb +1 -2
- data/lib/rubocop/cop/rails/bulk_change_table.rb +6 -20
- data/lib/rubocop/cop/rails/compact_blank.rb +5 -1
- data/lib/rubocop/cop/rails/content_tag.rb +3 -4
- data/lib/rubocop/cop/rails/date.rb +4 -9
- data/lib/rubocop/cop/rails/delegate.rb +2 -5
- data/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +17 -13
- data/lib/rubocop/cop/rails/dot_separated_keys.rb +1 -1
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +8 -6
- data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +4 -0
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -5
- data/lib/rubocop/cop/rails/environment_comparison.rb +1 -2
- data/lib/rubocop/cop/rails/file_path.rb +2 -4
- data/lib/rubocop/cop/rails/find_each.rb +8 -2
- data/lib/rubocop/cop/rails/freeze_time.rb +74 -0
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -3
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +4 -9
- data/lib/rubocop/cop/rails/http_status.rb +11 -11
- data/lib/rubocop/cop/rails/ignored_columns_assignment.rb +50 -0
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +3 -10
- data/lib/rubocop/cop/rails/inverse_of.rb +3 -6
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +2 -6
- data/lib/rubocop/cop/rails/link_to_blank.rb +1 -4
- data/lib/rubocop/cop/rails/output.rb +2 -5
- data/lib/rubocop/cop/rails/pluck.rb +8 -7
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +1 -2
- data/lib/rubocop/cop/rails/presence.rb +21 -12
- data/lib/rubocop/cop/rails/present.rb +3 -6
- data/lib/rubocop/cop/rails/rake_environment.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +2 -4
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +3 -3
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +30 -26
- data/lib/rubocop/cop/rails/reflection_class_name.rb +17 -0
- data/lib/rubocop/cop/rails/refute_methods.rb +1 -5
- data/lib/rubocop/cop/rails/relative_date_constant.rb +2 -5
- data/lib/rubocop/cop/rails/request_referer.rb +1 -2
- data/lib/rubocop/cop/rails/reversible_migration.rb +10 -33
- data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +1 -2
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +214 -0
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +1 -3
- data/lib/rubocop/cop/rails/save_bang.rb +10 -22
- data/lib/rubocop/cop/rails/short_i18n.rb +1 -4
- data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -2
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -5
- data/lib/rubocop/cop/rails/time_zone.rb +10 -21
- data/lib/rubocop/cop/rails/to_s_with_argument.rb +41 -0
- data/lib/rubocop/cop/rails/top_level_hash_with_indifferent_access.rb +49 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +3 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -3
- data/lib/rubocop/cop/rails/unknown_env.rb +2 -4
- data/lib/rubocop/cop/rails/validation.rb +4 -12
- data/lib/rubocop/cop/rails/where_missing.rb +111 -0
- data/lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb +55 -0
- data/lib/rubocop/cop/rails_cops.rb +10 -0
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop-rails.rb +10 -0
- metadata +16 -8
- data/bin/console +0 -11
- data/bin/setup +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a7a516c82d0953f3f1995b190ddc427aa251583287a9232229e82a218c93ba6
|
4
|
+
data.tar.gz: f224a35df6de69c04c7c6f6314f9cfa713cc5accfba1bbce9d5554c7fd50a121
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b3277765f3819855d3e29d3226c81ebc6231b1b1aaf583e1ae86db9e18b7b450bbc2b3f9bccaaa85623ca57e0ac139abde604c35bccc81c3081a80c4392f35d
|
7
|
+
data.tar.gz: a3d7b79f10c2090b04a05d1b30cc3c639645aa6b3c2ad33247fecfa7597907238d8f6e727a8e0dd088b92d69842c488489e9883f9acfd4551e08a9b8f3dd1f8c
|
data/config/default.yml
CHANGED
@@ -10,6 +10,12 @@ AllCops:
|
|
10
10
|
# Exclude db/schema.rb and db/[CONFIGURATION_NAMESPACE]_schema.rb by default.
|
11
11
|
# See: https://guides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application
|
12
12
|
- db/*schema.rb
|
13
|
+
- log/**/*
|
14
|
+
- public/**/*
|
15
|
+
- storage/**/*
|
16
|
+
# Enable checking Active Support extensions.
|
17
|
+
# See: https://docs.rubocop.org/rubocop/configuration.html#enable-checking-active-support-extensions
|
18
|
+
ActiveSupportExtensionsEnabled: true
|
13
19
|
# What version of Rails is the inspected code using? If a value is specified
|
14
20
|
# for TargetRailsVersion then it is used. Acceptable values are specified
|
15
21
|
# as a float (i.e. 5.1); the patch version of Rails should not be included.
|
@@ -23,6 +29,24 @@ Lint/NumberConversion:
|
|
23
29
|
# Add Rails' duration methods to the ignore list for `Lint/NumberConversion`
|
24
30
|
# so that calling `to_i` on one of these does not register an offense.
|
25
31
|
# See: https://github.com/rubocop/rubocop/issues/8950
|
32
|
+
AllowedMethods:
|
33
|
+
- ago
|
34
|
+
- from_now
|
35
|
+
- second
|
36
|
+
- seconds
|
37
|
+
- minute
|
38
|
+
- minutes
|
39
|
+
- hour
|
40
|
+
- hours
|
41
|
+
- day
|
42
|
+
- days
|
43
|
+
- week
|
44
|
+
- weeks
|
45
|
+
- fortnight
|
46
|
+
- fortnights
|
47
|
+
- in_milliseconds
|
48
|
+
AllowedPatterns: []
|
49
|
+
# Deprecated.
|
26
50
|
IgnoredMethods:
|
27
51
|
- ago
|
28
52
|
- from_now
|
@@ -40,6 +64,18 @@ Lint/NumberConversion:
|
|
40
64
|
- fortnights
|
41
65
|
- in_milliseconds
|
42
66
|
|
67
|
+
Rails:
|
68
|
+
Enabled: true
|
69
|
+
DocumentationBaseURL: https://docs.rubocop.org/rubocop-rails
|
70
|
+
|
71
|
+
Rails/ActionControllerFlashBeforeRender:
|
72
|
+
Description: 'Use `flash.now` instead of `flash` before `render`.'
|
73
|
+
StyleGuide: 'https://rails.rubystyle.guide/#flash-before-render'
|
74
|
+
Reference: 'https://api.rubyonrails.org/classes/ActionController/FlashBeforeRender.html'
|
75
|
+
Enabled: 'pending'
|
76
|
+
SafeAutocorrect: false
|
77
|
+
VersionAdded: '2.16'
|
78
|
+
|
43
79
|
Rails/ActionControllerTestCase:
|
44
80
|
Description: 'Use `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.'
|
45
81
|
StyleGuide: 'https://rails.rubystyle.guide/#integration-testing'
|
@@ -62,6 +98,21 @@ Rails/ActionFilter:
|
|
62
98
|
- app/controllers/**/*.rb
|
63
99
|
- app/mailers/**/*.rb
|
64
100
|
|
101
|
+
Rails/ActionOrder:
|
102
|
+
Description: 'Enforce consistent ordering of controller actions.'
|
103
|
+
Enabled: pending
|
104
|
+
VersionAdded: '2.17'
|
105
|
+
ExpectedOrder:
|
106
|
+
- index
|
107
|
+
- show
|
108
|
+
- new
|
109
|
+
- edit
|
110
|
+
- create
|
111
|
+
- update
|
112
|
+
- destroy
|
113
|
+
Include:
|
114
|
+
- app/controllers/**/*.rb
|
115
|
+
|
65
116
|
Rails/ActiveRecordAliases:
|
66
117
|
Description: >-
|
67
118
|
Avoid Active Record aliases:
|
@@ -96,6 +147,15 @@ Rails/ActiveSupportAliases:
|
|
96
147
|
Enabled: true
|
97
148
|
VersionAdded: '0.48'
|
98
149
|
|
150
|
+
Rails/ActiveSupportOnLoad:
|
151
|
+
Description: 'Use `ActiveSupport.on_load(...)` to patch Rails framework classes.'
|
152
|
+
Enabled: 'pending'
|
153
|
+
Reference:
|
154
|
+
- 'https://api.rubyonrails.org/classes/ActiveSupport/LazyLoadHooks.html'
|
155
|
+
- 'https://guides.rubyonrails.org/engines.html#available-load-hooks'
|
156
|
+
SafeAutoCorrect: false
|
157
|
+
VersionAdded: '2.16'
|
158
|
+
|
99
159
|
Rails/AddColumnIndex:
|
100
160
|
Description: >-
|
101
161
|
Rails migrations don't make use of a given `index` key, but also
|
@@ -306,10 +366,13 @@ Rails/DynamicFindBy:
|
|
306
366
|
# The `Whitelist` has been deprecated, Please use `AllowedMethods` instead.
|
307
367
|
Whitelist:
|
308
368
|
- find_by_sql
|
369
|
+
- find_by_token_for
|
309
370
|
AllowedMethods:
|
310
371
|
- find_by_sql
|
372
|
+
- find_by_token_for
|
311
373
|
AllowedReceivers:
|
312
374
|
- Gem::Specification
|
375
|
+
- page # Prevents a warning for `page.find_by_id`. See: https://github.com/rubocop/rubocop-rails/issues/778
|
313
376
|
|
314
377
|
Rails/EagerEvaluationLogMessage:
|
315
378
|
Description: 'Checks that blocks are used for interpolated strings passed to `Rails.logger.debug`.'
|
@@ -407,6 +470,14 @@ Rails/FindEach:
|
|
407
470
|
VersionChanged: '2.9'
|
408
471
|
Include:
|
409
472
|
- app/models/**/*.rb
|
473
|
+
AllowedMethods:
|
474
|
+
# Methods that don't work well with `find_each`.
|
475
|
+
- order
|
476
|
+
- limit
|
477
|
+
- select
|
478
|
+
- lock
|
479
|
+
AllowedPatterns: []
|
480
|
+
# Deprecated.
|
410
481
|
IgnoredMethods:
|
411
482
|
# Methods that don't work well with `find_each`.
|
412
483
|
- order
|
@@ -414,6 +485,13 @@ Rails/FindEach:
|
|
414
485
|
- select
|
415
486
|
- lock
|
416
487
|
|
488
|
+
Rails/FreezeTime:
|
489
|
+
Description: 'Prefer `freeze_time` over `travel_to` with an argument of the current time.'
|
490
|
+
StyleGuide: 'https://rails.rubystyle.guide/#freeze-time'
|
491
|
+
Enabled: pending
|
492
|
+
VersionAdded: '2.16'
|
493
|
+
SafeAutoCorrect: false
|
494
|
+
|
417
495
|
Rails/HasAndBelongsToMany:
|
418
496
|
Description: 'Prefer has_many :through to has_and_belongs_to_many.'
|
419
497
|
StyleGuide: 'https://rails.rubystyle.guide#has-many-through'
|
@@ -478,6 +556,13 @@ Rails/I18nLocaleTexts:
|
|
478
556
|
Enabled: pending
|
479
557
|
VersionAdded: '2.14'
|
480
558
|
|
559
|
+
Rails/IgnoredColumnsAssignment:
|
560
|
+
Description: 'Looks for assignments of `ignored_columns` that override previous assignments.'
|
561
|
+
StyleGuide: 'https://rails.rubystyle.guide/#append-ignored-columns'
|
562
|
+
Enabled: pending
|
563
|
+
SafeAutoCorrect: false
|
564
|
+
VersionAdded: '2.17'
|
565
|
+
|
481
566
|
Rails/IgnoredSkipActionFilterOption:
|
482
567
|
Description: 'Checks that `if` and `only` (or `except`) are not used together as options of `skip_*` action filter.'
|
483
568
|
Reference: 'https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options'
|
@@ -785,6 +870,12 @@ Rails/RootJoinChain:
|
|
785
870
|
Enabled: pending
|
786
871
|
VersionAdded: '2.13'
|
787
872
|
|
873
|
+
Rails/RootPathnameMethods:
|
874
|
+
Description: 'Use `Rails.root` IO methods instead of passing it to `File`.'
|
875
|
+
Enabled: pending
|
876
|
+
SafeAutocorrect: false
|
877
|
+
VersionAdded: '2.16'
|
878
|
+
|
788
879
|
Rails/RootPublicPath:
|
789
880
|
Description: "Favor `Rails.public_path` over `Rails.root` with `'public'`."
|
790
881
|
Enabled: pending
|
@@ -937,6 +1028,18 @@ Rails/ToFormattedS:
|
|
937
1028
|
- to_formatted_s
|
938
1029
|
VersionAdded: '2.15'
|
939
1030
|
|
1031
|
+
Rails/ToSWithArgument:
|
1032
|
+
Description: 'Identifies passing any argument to `#to_s`.'
|
1033
|
+
Enabled: pending
|
1034
|
+
Safe: false
|
1035
|
+
VersionAdded: '2.16'
|
1036
|
+
|
1037
|
+
Rails/TopLevelHashWithIndifferentAccess:
|
1038
|
+
Description: 'Identifies top-level `HashWithIndifferentAccess`.'
|
1039
|
+
Reference: 'https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#top-level-hashwithindifferentaccess-is-soft-deprecated'
|
1040
|
+
Enabled: pending
|
1041
|
+
VersionAdded: '2.16'
|
1042
|
+
|
940
1043
|
Rails/TransactionExitStatement:
|
941
1044
|
Description: 'Avoid the usage of `return`, `break` and `throw` in transaction blocks.'
|
942
1045
|
Enabled: pending
|
@@ -1003,12 +1106,29 @@ Rails/WhereExists:
|
|
1003
1106
|
VersionAdded: '2.7'
|
1004
1107
|
VersionChanged: '2.10'
|
1005
1108
|
|
1109
|
+
Rails/WhereMissing:
|
1110
|
+
Description: 'Use `where.missing(...)` to find missing relationship records.'
|
1111
|
+
StyleGuide: 'https://rails.rubystyle.guide/#finding-missing-relationship-records'
|
1112
|
+
Enabled: pending
|
1113
|
+
VersionAdded: '2.16'
|
1114
|
+
|
1006
1115
|
Rails/WhereNot:
|
1007
1116
|
Description: 'Use `where.not(...)` instead of manually constructing negated SQL in `where`.'
|
1008
1117
|
StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
|
1009
1118
|
Enabled: 'pending'
|
1010
1119
|
VersionAdded: '2.8'
|
1011
1120
|
|
1121
|
+
Rails/WhereNotWithMultipleConditions:
|
1122
|
+
Description: 'Do not use `where.not(...)` with multiple conditions.'
|
1123
|
+
Enabled: 'pending'
|
1124
|
+
VersionAdded: '2.17'
|
1125
|
+
|
1012
1126
|
# Accept `redirect_to(...) and return` and similar cases.
|
1013
1127
|
Style/AndOr:
|
1014
1128
|
EnforcedStyle: conditionals
|
1129
|
+
|
1130
|
+
Style/SymbolProc:
|
1131
|
+
AllowedMethods:
|
1132
|
+
- define_method
|
1133
|
+
- mail
|
1134
|
+
- respond_to
|
data/config/obsoletion.yml
CHANGED
@@ -5,3 +5,13 @@
|
|
5
5
|
#
|
6
6
|
extracted:
|
7
7
|
Rails/*: ~
|
8
|
+
|
9
|
+
# Cop parameters that have been changed
|
10
|
+
# Can be treated as a warning instead of a failure with `severity: warning`
|
11
|
+
changed_parameters:
|
12
|
+
- cops: Rails/FindEach
|
13
|
+
parameters: IgnoredMethods
|
14
|
+
alternatives:
|
15
|
+
- AllowedMethods
|
16
|
+
- AllowedPatterns
|
17
|
+
severity: warning
|
@@ -48,10 +48,7 @@ module RuboCop
|
|
48
48
|
|
49
49
|
class_nodes = class_node.defined_module.each_node
|
50
50
|
namespaces = class_node.each_ancestor(:class, :module).map(&:identifier)
|
51
|
-
[*class_nodes, *namespaces]
|
52
|
-
.reverse
|
53
|
-
.map { |node| node.children[1] }.join('_')
|
54
|
-
.tableize
|
51
|
+
[*class_nodes, *namespaces].reverse.map { |node| node.children[1] }.join('_').tableize
|
55
52
|
end
|
56
53
|
|
57
54
|
# Resolve relation into column name.
|
@@ -10,9 +10,7 @@ module RuboCop
|
|
10
10
|
bigint binary boolean date datetime decimal float integer json string
|
11
11
|
text time timestamp virtual
|
12
12
|
].freeze
|
13
|
-
RAILS_ABSTRACT_SCHEMA_DEFINITIONS_HELPERS = %i[
|
14
|
-
column references belongs_to primary_key numeric
|
15
|
-
].freeze
|
13
|
+
RAILS_ABSTRACT_SCHEMA_DEFINITIONS_HELPERS = %i[column references belongs_to primary_key numeric].freeze
|
16
14
|
POSTGRES_SCHEMA_DEFINITIONS = %i[
|
17
15
|
bigserial bit bit_varying cidr citext daterange hstore inet interval
|
18
16
|
int4range int8range jsonb ltree macaddr money numrange oid point line
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
module IndexMethod # rubocop:disable Metrics/ModuleLength
|
7
7
|
RESTRICT_ON_SEND = %i[each_with_object to_h map collect []].freeze
|
8
8
|
|
9
|
-
def on_block(node)
|
9
|
+
def on_block(node) # rubocop:todo InternalAffairs/NumblockHandler
|
10
10
|
on_bad_each_with_object(node) do |*match|
|
11
11
|
handle_possible_offense(node, match, 'each_with_object')
|
12
12
|
end
|
@@ -98,10 +98,7 @@ module RuboCop
|
|
98
98
|
|
99
99
|
captures = extract_captures(correction.match)
|
100
100
|
correction.set_new_arg_name(captures.transformed_argname, corrector)
|
101
|
-
correction.set_new_body_expression(
|
102
|
-
captures.transforming_body_expr,
|
103
|
-
corrector
|
104
|
-
)
|
101
|
+
correction.set_new_body_expression(captures.transforming_body_expr, corrector)
|
105
102
|
end
|
106
103
|
|
107
104
|
# Internal helper class to hold match data
|
@@ -110,8 +107,7 @@ module RuboCop
|
|
110
107
|
:transforming_body_expr
|
111
108
|
) do
|
112
109
|
def noop_transformation?
|
113
|
-
transforming_body_expr.lvar_type? &&
|
114
|
-
transforming_body_expr.children == [transformed_argname]
|
110
|
+
transforming_body_expr.lvar_type? && transforming_body_expr.children == [transformed_argname]
|
115
111
|
end
|
116
112
|
end
|
117
113
|
|
@@ -157,17 +153,11 @@ module RuboCop
|
|
157
153
|
end
|
158
154
|
|
159
155
|
def set_new_arg_name(transformed_argname, corrector)
|
160
|
-
corrector.replace(
|
161
|
-
block_node.arguments.loc.expression,
|
162
|
-
"|#{transformed_argname}|"
|
163
|
-
)
|
156
|
+
corrector.replace(block_node.arguments.loc.expression, "|#{transformed_argname}|")
|
164
157
|
end
|
165
158
|
|
166
159
|
def set_new_body_expression(transforming_body_expr, corrector)
|
167
|
-
corrector.replace(
|
168
|
-
block_node.body.loc.expression,
|
169
|
-
transforming_body_expr.loc.expression.source
|
170
|
-
)
|
160
|
+
corrector.replace(block_node.body.loc.expression, transforming_body_expr.loc.expression.source)
|
171
161
|
end
|
172
162
|
end
|
173
163
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Using `flash` assignment before `render` in Rails controllers will persist the message for too long.
|
7
|
+
# Check https://guides.rubyonrails.org/action_controller_overview.html#flash-now
|
8
|
+
#
|
9
|
+
# @safety
|
10
|
+
# This cop's autocorrection is unsafe because it replaces `flash` by `flash.now`.
|
11
|
+
# Even though it is usually a mistake, it might be used intentionally.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# class HomeController < ApplicationController
|
17
|
+
# def create
|
18
|
+
# flash[:alert] = "msg"
|
19
|
+
# render :index
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# class HomeController < ApplicationController
|
25
|
+
# def create
|
26
|
+
# flash.now[:alert] = "msg"
|
27
|
+
# render :index
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
class ActionControllerFlashBeforeRender < Base
|
32
|
+
extend AutoCorrector
|
33
|
+
|
34
|
+
MSG = 'Use `flash.now` before `render`.'
|
35
|
+
|
36
|
+
def_node_search :flash_assignment?, <<~PATTERN
|
37
|
+
^(send (send nil? :flash) :[]= ...)
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
def_node_search :redirect_to?, <<~PATTERN
|
41
|
+
(send nil? :redirect_to ...)
|
42
|
+
PATTERN
|
43
|
+
|
44
|
+
def_node_search :action_controller?, <<~PATTERN
|
45
|
+
{
|
46
|
+
(const nil? :ApplicationController)
|
47
|
+
(const (const nil? :ActionController) :Base)
|
48
|
+
}
|
49
|
+
PATTERN
|
50
|
+
|
51
|
+
RESTRICT_ON_SEND = [:flash].freeze
|
52
|
+
|
53
|
+
def on_send(flash_node)
|
54
|
+
return unless flash_assignment?(flash_node)
|
55
|
+
|
56
|
+
return if followed_by_redirect_to?(flash_node)
|
57
|
+
|
58
|
+
return unless instance_method_or_block?(flash_node)
|
59
|
+
|
60
|
+
return unless inherit_action_controller_base?(flash_node)
|
61
|
+
|
62
|
+
add_offense(flash_node) do |corrector|
|
63
|
+
corrector.replace(flash_node, 'flash.now')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def followed_by_redirect_to?(flash_node)
|
70
|
+
flash_assigment_node = find_ancestor(flash_node, type: :send)
|
71
|
+
context = flash_assigment_node.parent
|
72
|
+
|
73
|
+
flash_index = context.children.index(flash_assigment_node)
|
74
|
+
context.each_child_node.with_index.any? do |node, index|
|
75
|
+
index > flash_index && redirect_to?(node)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def inherit_action_controller_base?(node)
|
80
|
+
class_node = find_ancestor(node, type: :class)
|
81
|
+
return unless class_node
|
82
|
+
|
83
|
+
action_controller?(class_node)
|
84
|
+
end
|
85
|
+
|
86
|
+
def instance_method_or_block?(node)
|
87
|
+
def_node = find_ancestor(node, type: :def)
|
88
|
+
block_node = find_ancestor(node, type: :block)
|
89
|
+
|
90
|
+
def_node || block_node
|
91
|
+
end
|
92
|
+
|
93
|
+
def find_ancestor(node, type:)
|
94
|
+
node.each_ancestor(type).first
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
def_node_matcher :action_controller_test_case?, <<~PATTERN
|
32
32
|
(class
|
33
33
|
(const nil? _)
|
34
|
-
(const (const {nil? cbase} :ActionController) :TestCase)
|
34
|
+
(const (const {nil? cbase} :ActionController) :TestCase) _)
|
35
35
|
PATTERN
|
36
36
|
|
37
37
|
def on_class(node)
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Enforces consistent ordering of the standard Rails RESTful controller actions.
|
7
|
+
#
|
8
|
+
# The cop is configurable and can enforce any ordering of the standard actions.
|
9
|
+
# All other methods are ignored.
|
10
|
+
#
|
11
|
+
# [source,yaml]
|
12
|
+
# ----
|
13
|
+
# Rails/ActionOrder:
|
14
|
+
# ExpectedOrder:
|
15
|
+
# - index
|
16
|
+
# - show
|
17
|
+
# - new
|
18
|
+
# - edit
|
19
|
+
# - create
|
20
|
+
# - update
|
21
|
+
# - destroy
|
22
|
+
# ----
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# # bad
|
26
|
+
# def index; end
|
27
|
+
# def destroy; end
|
28
|
+
# def show; end
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# def index; end
|
32
|
+
# def show; end
|
33
|
+
# def destroy; end
|
34
|
+
class ActionOrder < Base
|
35
|
+
extend AutoCorrector
|
36
|
+
include VisibilityHelp
|
37
|
+
include DefNode
|
38
|
+
|
39
|
+
MSG = 'Action `%<current>s` should appear before `%<previous>s`.'
|
40
|
+
|
41
|
+
def_node_search :action_declarations, '(def {%1} ...)'
|
42
|
+
|
43
|
+
def on_class(node)
|
44
|
+
action_declarations(node, actions).each_cons(2) do |previous, current|
|
45
|
+
next if node_visibility(current) != :public || non_public?(current)
|
46
|
+
next if find_index(current) >= find_index(previous)
|
47
|
+
|
48
|
+
register_offense(previous, current)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def expected_order
|
55
|
+
cop_config['ExpectedOrder'].map(&:to_sym)
|
56
|
+
end
|
57
|
+
|
58
|
+
def actions
|
59
|
+
@actions ||= Set.new(expected_order)
|
60
|
+
end
|
61
|
+
|
62
|
+
def find_index(node)
|
63
|
+
expected_order.find_index(node.method_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def register_offense(previous, current)
|
67
|
+
message = format(
|
68
|
+
MSG,
|
69
|
+
expected_order: expected_order.join(', '),
|
70
|
+
previous: previous.method_name,
|
71
|
+
current: current.method_name
|
72
|
+
)
|
73
|
+
add_offense(current, message: message) do |corrector|
|
74
|
+
corrector.replace(current, previous.source)
|
75
|
+
corrector.replace(previous, current.source)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -21,10 +21,7 @@ module RuboCop
|
|
21
21
|
|
22
22
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
23
23
|
|
24
|
-
ALIASES = {
|
25
|
-
update_attributes: :update,
|
26
|
-
update_attributes!: :update!
|
27
|
-
}.freeze
|
24
|
+
ALIASES = { update_attributes: :update, update_attributes!: :update! }.freeze
|
28
25
|
|
29
26
|
RESTRICT_ON_SEND = ALIASES.keys.freeze
|
30
27
|
|
@@ -25,12 +25,9 @@ module RuboCop
|
|
25
25
|
# end
|
26
26
|
#
|
27
27
|
class ActiveRecordOverride < Base
|
28
|
-
MSG =
|
29
|
-
'Use %<prefer>s callbacks instead of overriding the Active Record ' \
|
30
|
-
'method `%<bad>s`.'
|
28
|
+
MSG = 'Use %<prefer>s callbacks instead of overriding the Active Record method `%<bad>s`.'
|
31
29
|
BAD_METHODS = %i[create destroy save update].freeze
|
32
|
-
ACTIVE_RECORD_CLASSES = %w[ApplicationRecord ActiveModel::Base
|
33
|
-
ActiveRecord::Base].freeze
|
30
|
+
ACTIVE_RECORD_CLASSES = %w[ApplicationRecord ActiveModel::Base ActiveRecord::Base].freeze
|
34
31
|
|
35
32
|
def on_def(node)
|
36
33
|
return unless BAD_METHODS.include?(node.method_name)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Checks for Rails framework classes that are patched directly instead of using Active Support load hooks. Direct
|
7
|
+
# patching forcibly loads the framework referenced, using hooks defers loading until it's actually needed.
|
8
|
+
#
|
9
|
+
# @safety
|
10
|
+
# While using lazy load hooks is recommended, it changes the order in which is code is loaded and may reveal
|
11
|
+
# load order dependency bugs.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# ActiveRecord::Base.include(MyClass)
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# ActiveSupport.on_load(:active_record) { include MyClass }
|
20
|
+
class ActiveSupportOnLoad < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
24
|
+
RESTRICT_ON_SEND = %i[prepend include extend].freeze
|
25
|
+
LOAD_HOOKS = {
|
26
|
+
'ActionCable' => 'action_cable',
|
27
|
+
'ActionCable::Channel::Base' => 'action_cable_channel',
|
28
|
+
'ActionCable::Connection::Base' => 'action_cable_connection',
|
29
|
+
'ActionCable::Connection::TestCase' => 'action_cable_connection_test_case',
|
30
|
+
'ActionController::API' => 'action_controller',
|
31
|
+
'ActionController::Base' => 'action_controller',
|
32
|
+
'ActionController::TestCase' => 'action_controller_test_case',
|
33
|
+
'ActionDispatch::IntegrationTest' => 'action_dispatch_integration_test',
|
34
|
+
'ActionDispatch::Request' => 'action_dispatch_request',
|
35
|
+
'ActionDispatch::Response' => 'action_dispatch_response',
|
36
|
+
'ActionDispatch::SystemTestCase' => 'action_dispatch_system_test_case',
|
37
|
+
'ActionMailbox::Base' => 'action_mailbox',
|
38
|
+
'ActionMailbox::InboundEmail' => 'action_mailbox_inbound_email',
|
39
|
+
'ActionMailbox::Record' => 'action_mailbox_record',
|
40
|
+
'ActionMailbox::TestCase' => 'action_mailbox_test_case',
|
41
|
+
'ActionMailer::Base' => 'action_mailer',
|
42
|
+
'ActionMailer::TestCase' => 'action_mailer_test_case',
|
43
|
+
'ActionText::Content' => 'action_text_content',
|
44
|
+
'ActionText::Record' => 'action_text_record',
|
45
|
+
'ActionText::RichText' => 'action_text_rich_text',
|
46
|
+
'ActionView::Base' => 'action_view',
|
47
|
+
'ActionView::TestCase' => 'action_view_test_case',
|
48
|
+
'ActiveJob::Base' => 'active_job',
|
49
|
+
'ActiveJob::TestCase' => 'active_job_test_case',
|
50
|
+
'ActiveRecord::Base' => 'active_record',
|
51
|
+
'ActiveStorage::Attachment' => 'active_storage_attachment',
|
52
|
+
'ActiveStorage::Blob' => 'active_storage_blob',
|
53
|
+
'ActiveStorage::Record' => 'active_storage_record',
|
54
|
+
'ActiveStorage::VariantRecord' => 'active_storage_variant_record',
|
55
|
+
'ActiveSupport::TestCase' => 'active_support_test_case'
|
56
|
+
}.freeze
|
57
|
+
|
58
|
+
def on_send(node)
|
59
|
+
receiver, method, arguments = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
60
|
+
return unless receiver && (hook = LOAD_HOOKS[receiver.const_name])
|
61
|
+
|
62
|
+
preferred = "ActiveSupport.on_load(:#{hook}) { #{method} #{arguments.source} }"
|
63
|
+
add_offense(node, message: format(MSG, prefer: preferred, current: node.source)) do |corrector|
|
64
|
+
corrector.replace(node, preferred)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -53,10 +53,7 @@ module RuboCop
|
|
53
53
|
private
|
54
54
|
|
55
55
|
def index_range(pair_node)
|
56
|
-
range_with_surrounding_comma(
|
57
|
-
range_with_surrounding_space(range: pair_node.loc.expression, side: :left),
|
58
|
-
:left
|
59
|
-
)
|
56
|
+
range_with_surrounding_comma(range_with_surrounding_space(pair_node.loc.expression, side: :left), :left)
|
60
57
|
end
|
61
58
|
end
|
62
59
|
end
|
@@ -63,8 +63,7 @@ module RuboCop
|
|
63
63
|
|
64
64
|
MSG_NIL_OR_EMPTY = 'Use `%<prefer>s` instead of `%<current>s`.'
|
65
65
|
MSG_NOT_PRESENT = 'Use `%<prefer>s` instead of `%<current>s`.'
|
66
|
-
MSG_UNLESS_PRESENT = 'Use `if %<prefer>s` instead of '
|
67
|
-
'`%<current>s`.'
|
66
|
+
MSG_UNLESS_PRESENT = 'Use `if %<prefer>s` instead of `%<current>s`.'
|
68
67
|
RESTRICT_ON_SEND = %i[!].freeze
|
69
68
|
|
70
69
|
# `(send nil $_)` is not actually a valid match for an offense. Nodes
|