rubocop-rails 2.15.0 → 2.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/default.yml +82 -1
- 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 +98 -0
- data/lib/rubocop/cop/rails/action_filter.rb +1 -1
- 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 +1 -3
- data/lib/rubocop/cop/rails/date.rb +4 -9
- data/lib/rubocop/cop/rails/delegate.rb +6 -14
- data/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +18 -12
- data/lib/rubocop/cop/rails/dot_separated_keys.rb +2 -2
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +2 -4
- data/lib/rubocop/cop/rails/enum_hash.rb +1 -2
- 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/expanded_date_range.rb +38 -22
- 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 +69 -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 +5 -10
- 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/order_by_id.rb +1 -2
- data/lib/rubocop/cop/rails/output.rb +2 -5
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +1 -2
- data/lib/rubocop/cop/rails/presence.rb +1 -3
- 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 +2 -2
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +28 -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 +175 -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/strip_heredoc.rb +1 -1
- data/lib/rubocop/cop/rails/time_zone.rb +8 -19
- data/lib/rubocop/cop/rails/time_zone_assignment.rb +2 -2
- data/lib/rubocop/cop/rails/to_formatted_s.rb +1 -0
- data/lib/rubocop/cop/rails/to_s_with_argument.rb +41 -0
- data/lib/rubocop/cop/rails/top_level_hash_with_indifferent_access.rb +48 -0
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +1 -1
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +3 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +3 -5
- 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_cops.rb +7 -0
- data/lib/rubocop/rails/schema_loader/schema.rb +5 -5
- data/lib/rubocop/rails/version.rb +1 -1
- metadata +13 -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: a928896af6bef8228bfc2530b829a683154c23b22ea547557d40ea1e4d08ae7f
|
4
|
+
data.tar.gz: 40303c4d80e1e6eaef12ceb0170b64b65b151fc2056957d6c6b6bac1d645d445
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a87b9c167cf43287207bae3ec38e385cb6213c26ff0f7e10aa3bf392ab28b724794820a459dc6af6d464e48ea70629c443e74acc4539dca6f0c0a57fee65d87c
|
7
|
+
data.tar.gz: fbb0b7333c6d485e50facadd7170bb2d59e425119134d01f42ac3d24eecc01ad52d588f55de184c9373061ba207cf6845d3e8201fe43ce48e3a8d3b22e992dff
|
data/config/default.yml
CHANGED
@@ -10,6 +10,9 @@ 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
|
+
# Enable checking Active Support extensions.
|
14
|
+
# See: https://docs.rubocop.org/rubocop/configuration.html#enable-checking-active-support-extensions
|
15
|
+
ActiveSupportExtensionsEnabled: true
|
13
16
|
# What version of Rails is the inspected code using? If a value is specified
|
14
17
|
# for TargetRailsVersion then it is used. Acceptable values are specified
|
15
18
|
# as a float (i.e. 5.1); the patch version of Rails should not be included.
|
@@ -23,6 +26,24 @@ Lint/NumberConversion:
|
|
23
26
|
# Add Rails' duration methods to the ignore list for `Lint/NumberConversion`
|
24
27
|
# so that calling `to_i` on one of these does not register an offense.
|
25
28
|
# See: https://github.com/rubocop/rubocop/issues/8950
|
29
|
+
AllowedMethods:
|
30
|
+
- ago
|
31
|
+
- from_now
|
32
|
+
- second
|
33
|
+
- seconds
|
34
|
+
- minute
|
35
|
+
- minutes
|
36
|
+
- hour
|
37
|
+
- hours
|
38
|
+
- day
|
39
|
+
- days
|
40
|
+
- week
|
41
|
+
- weeks
|
42
|
+
- fortnight
|
43
|
+
- fortnights
|
44
|
+
- in_milliseconds
|
45
|
+
AllowedPatterns: []
|
46
|
+
# Deprecated.
|
26
47
|
IgnoredMethods:
|
27
48
|
- ago
|
28
49
|
- from_now
|
@@ -40,6 +61,18 @@ Lint/NumberConversion:
|
|
40
61
|
- fortnights
|
41
62
|
- in_milliseconds
|
42
63
|
|
64
|
+
Rails:
|
65
|
+
Enabled: true
|
66
|
+
DocumentationBaseURL: https://docs.rubocop.org/rubocop-rails
|
67
|
+
|
68
|
+
Rails/ActionControllerFlashBeforeRender:
|
69
|
+
Description: 'Use `flash.now` instead of `flash` before `render`.'
|
70
|
+
StyleGuide: 'https://rails.rubystyle.guide/#flash-before-render'
|
71
|
+
Reference: 'https://api.rubyonrails.org/classes/ActionController/FlashBeforeRender.html'
|
72
|
+
Enabled: 'pending'
|
73
|
+
SafeAutocorrect: false
|
74
|
+
VersionAdded: '2.16'
|
75
|
+
|
43
76
|
Rails/ActionControllerTestCase:
|
44
77
|
Description: 'Use `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.'
|
45
78
|
StyleGuide: 'https://rails.rubystyle.guide/#integration-testing'
|
@@ -96,6 +129,15 @@ Rails/ActiveSupportAliases:
|
|
96
129
|
Enabled: true
|
97
130
|
VersionAdded: '0.48'
|
98
131
|
|
132
|
+
Rails/ActiveSupportOnLoad:
|
133
|
+
Description: 'Use `ActiveSupport.on_load(...)` to patch Rails framework classes.'
|
134
|
+
Enabled: 'pending'
|
135
|
+
Reference:
|
136
|
+
- 'https://api.rubyonrails.org/classes/ActiveSupport/LazyLoadHooks.html'
|
137
|
+
- 'https://guides.rubyonrails.org/engines.html#available-load-hooks'
|
138
|
+
SafeAutoCorrect: false
|
139
|
+
VersionAdded: '2.16'
|
140
|
+
|
99
141
|
Rails/AddColumnIndex:
|
100
142
|
Description: >-
|
101
143
|
Rails migrations don't make use of a given `index` key, but also
|
@@ -160,7 +202,7 @@ Rails/AttributeDefaultBlockValue:
|
|
160
202
|
Enabled: pending
|
161
203
|
VersionAdded: '2.9'
|
162
204
|
Include:
|
163
|
-
- 'models/**/*'
|
205
|
+
- 'app/models/**/*'
|
164
206
|
|
165
207
|
Rails/BelongsTo:
|
166
208
|
Description: >-
|
@@ -367,6 +409,7 @@ Rails/Exit:
|
|
367
409
|
|
368
410
|
Rails/ExpandedDateRange:
|
369
411
|
Description: 'Checks for expanded date range.'
|
412
|
+
StyleGuide: 'https://rails.rubystyle.guide/#date-time-range'
|
370
413
|
Enabled: pending
|
371
414
|
VersionAdded: '2.11'
|
372
415
|
|
@@ -406,6 +449,14 @@ Rails/FindEach:
|
|
406
449
|
VersionChanged: '2.9'
|
407
450
|
Include:
|
408
451
|
- app/models/**/*.rb
|
452
|
+
AllowedMethods:
|
453
|
+
# Methods that don't work well with `find_each`.
|
454
|
+
- order
|
455
|
+
- limit
|
456
|
+
- select
|
457
|
+
- lock
|
458
|
+
AllowedPatterns: []
|
459
|
+
# Deprecated.
|
409
460
|
IgnoredMethods:
|
410
461
|
# Methods that don't work well with `find_each`.
|
411
462
|
- order
|
@@ -413,6 +464,13 @@ Rails/FindEach:
|
|
413
464
|
- select
|
414
465
|
- lock
|
415
466
|
|
467
|
+
Rails/FreezeTime:
|
468
|
+
Description: 'Prefer `freeze_time` over `travel_to` with an argument of the current time.'
|
469
|
+
StyleGuide: 'https://rails.rubystyle.guide/#freeze-time'
|
470
|
+
Enabled: pending
|
471
|
+
VersionAdded: '2.16'
|
472
|
+
SafeAutoCorrect: false
|
473
|
+
|
416
474
|
Rails/HasAndBelongsToMany:
|
417
475
|
Description: 'Prefer has_many :through to has_and_belongs_to_many.'
|
418
476
|
StyleGuide: 'https://rails.rubystyle.guide#has-many-through'
|
@@ -784,6 +842,11 @@ Rails/RootJoinChain:
|
|
784
842
|
Enabled: pending
|
785
843
|
VersionAdded: '2.13'
|
786
844
|
|
845
|
+
Rails/RootPathnameMethods:
|
846
|
+
Description: 'Use `Rails.root` IO methods instead of passing it to `File`.'
|
847
|
+
Enabled: pending
|
848
|
+
VersionAdded: '2.16'
|
849
|
+
|
787
850
|
Rails/RootPublicPath:
|
788
851
|
Description: "Favor `Rails.public_path` over `Rails.root` with `'public'`."
|
789
852
|
Enabled: pending
|
@@ -936,6 +999,18 @@ Rails/ToFormattedS:
|
|
936
999
|
- to_formatted_s
|
937
1000
|
VersionAdded: '2.15'
|
938
1001
|
|
1002
|
+
Rails/ToSWithArgument:
|
1003
|
+
Description: 'Identifies passing any argument to `#to_s`.'
|
1004
|
+
Enabled: pending
|
1005
|
+
Safe: false
|
1006
|
+
VersionAdded: '2.16'
|
1007
|
+
|
1008
|
+
Rails/TopLevelHashWithIndifferentAccess:
|
1009
|
+
Description: 'Identifies top-level `HashWithIndifferentAccess`.'
|
1010
|
+
Reference: 'https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#top-level-hashwithindifferentaccess-is-soft-deprecated'
|
1011
|
+
Enabled: pending
|
1012
|
+
VersionAdded: '2.16'
|
1013
|
+
|
939
1014
|
Rails/TransactionExitStatement:
|
940
1015
|
Description: 'Avoid the usage of `return`, `break` and `throw` in transaction blocks.'
|
941
1016
|
Enabled: pending
|
@@ -1002,6 +1077,12 @@ Rails/WhereExists:
|
|
1002
1077
|
VersionAdded: '2.7'
|
1003
1078
|
VersionChanged: '2.10'
|
1004
1079
|
|
1080
|
+
Rails/WhereMissing:
|
1081
|
+
Description: 'Use `where.missing(...)` to find missing relationship records.'
|
1082
|
+
StyleGuide: 'https://rails.rubystyle.guide/#finding-missing-relationship-records'
|
1083
|
+
Enabled: pending
|
1084
|
+
VersionAdded: '2.16'
|
1085
|
+
|
1005
1086
|
Rails/WhereNot:
|
1006
1087
|
Description: 'Use `where.not(...)` instead of manually constructing negated SQL in `where`.'
|
1007
1088
|
StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
|
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,98 @@
|
|
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 :render?, <<~PATTERN
|
41
|
+
(send nil? :render ...)
|
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 unless followed_by_render?(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_render?(flash_node)
|
70
|
+
flash_assigment_node = find_ancestor(flash_node, type: :send)
|
71
|
+
context = flash_assigment_node.parent
|
72
|
+
|
73
|
+
context.each_child_node.any? do |node|
|
74
|
+
render?(node)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def inherit_action_controller_base?(node)
|
79
|
+
class_node = find_ancestor(node, type: :class)
|
80
|
+
return unless class_node
|
81
|
+
|
82
|
+
action_controller?(class_node)
|
83
|
+
end
|
84
|
+
|
85
|
+
def instance_method_or_block?(node)
|
86
|
+
def_node = find_ancestor(node, type: :def)
|
87
|
+
block_node = find_ancestor(node, type: :block)
|
88
|
+
|
89
|
+
def_node || block_node
|
90
|
+
end
|
91
|
+
|
92
|
+
def find_ancestor(node, type:)
|
93
|
+
node.each_ancestor(type).first
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
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
|
@@ -111,25 +111,13 @@ module RuboCop
|
|
111
111
|
remove_timestamps
|
112
112
|
].freeze
|
113
113
|
|
114
|
-
MYSQL_COMBINABLE_TRANSFORMATIONS = %i[
|
115
|
-
rename
|
116
|
-
index
|
117
|
-
remove_index
|
118
|
-
].freeze
|
114
|
+
MYSQL_COMBINABLE_TRANSFORMATIONS = %i[rename index remove_index].freeze
|
119
115
|
|
120
|
-
MYSQL_COMBINABLE_ALTER_METHODS = %i[
|
121
|
-
rename_column
|
122
|
-
add_index
|
123
|
-
remove_index
|
124
|
-
].freeze
|
116
|
+
MYSQL_COMBINABLE_ALTER_METHODS = %i[rename_column add_index remove_index].freeze
|
125
117
|
|
126
|
-
POSTGRESQL_COMBINABLE_TRANSFORMATIONS = %i[
|
127
|
-
change_default
|
128
|
-
].freeze
|
118
|
+
POSTGRESQL_COMBINABLE_TRANSFORMATIONS = %i[change_default].freeze
|
129
119
|
|
130
|
-
POSTGRESQL_COMBINABLE_ALTER_METHODS = %i[
|
131
|
-
change_column_default
|
132
|
-
].freeze
|
120
|
+
POSTGRESQL_COMBINABLE_ALTER_METHODS = %i[change_column_default].freeze
|
133
121
|
|
134
122
|
def on_def(node)
|
135
123
|
return unless support_bulk_alter?
|
@@ -186,8 +174,7 @@ module RuboCop
|
|
186
174
|
options = node.arguments[1]
|
187
175
|
return false unless options
|
188
176
|
|
189
|
-
options.hash_type? &&
|
190
|
-
options.keys.any? { |key| key.sym_type? && key.value == :bulk }
|
177
|
+
options.hash_type? && options.keys.any? { |key| key.sym_type? && key.value == :bulk }
|
191
178
|
end
|
192
179
|
|
193
180
|
def database
|
@@ -237,8 +224,7 @@ module RuboCop
|
|
237
224
|
end
|
238
225
|
|
239
226
|
def call_to_combinable_alter_method?(child_node)
|
240
|
-
child_node.send_type? &&
|
241
|
-
combinable_alter_methods.include?(child_node.method_name)
|
227
|
+
child_node.send_type? && combinable_alter_methods.include?(child_node.method_name)
|
242
228
|
end
|
243
229
|
|
244
230
|
def combinable_alter_methods
|
@@ -93,7 +93,11 @@ module RuboCop
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def offense_range(node)
|
96
|
-
end_pos = node.parent&.block_type?
|
96
|
+
end_pos = if node.parent&.block_type? && node.parent&.send_node == node
|
97
|
+
node.parent.loc.expression.end_pos
|
98
|
+
else
|
99
|
+
node.loc.expression.end_pos
|
100
|
+
end
|
97
101
|
|
98
102
|
range_between(node.loc.selector.begin_pos, end_pos)
|
99
103
|
end
|
@@ -37,9 +37,7 @@ module RuboCop
|
|
37
37
|
return if node.arguments.count >= 3
|
38
38
|
|
39
39
|
first_argument = node.first_argument
|
40
|
-
return if !first_argument ||
|
41
|
-
allowed_argument?(first_argument) ||
|
42
|
-
corrected_ancestor?(node)
|
40
|
+
return if !first_argument || allowed_argument?(first_argument) || corrected_ancestor?(node)
|
43
41
|
|
44
42
|
preferred_method = node.first_argument.value.to_s.underscore
|
45
43
|
message = format(MSG, preferred_method: preferred_method, current_argument: first_argument.source)
|
@@ -53,22 +53,17 @@ module RuboCop
|
|
53
53
|
class Date < Base
|
54
54
|
include ConfigurableEnforcedStyle
|
55
55
|
|
56
|
-
MSG = 'Do not use `Date.%<method_called>s` without zone. Use '
|
57
|
-
'`Time.zone.%<day>s` instead.'
|
56
|
+
MSG = 'Do not use `Date.%<method_called>s` without zone. Use `Time.zone.%<day>s` instead.'
|
58
57
|
|
59
|
-
MSG_SEND = 'Do not use `%<method>s` on Date objects, because they '
|
60
|
-
'know nothing about the time zone in use.'
|
58
|
+
MSG_SEND = 'Do not use `%<method>s` on Date objects, because they know nothing about the time zone in use.'
|
61
59
|
|
62
60
|
RESTRICT_ON_SEND = %i[to_time to_time_in_current_zone].freeze
|
63
61
|
|
64
62
|
BAD_DAYS = %i[today current yesterday tomorrow].freeze
|
65
63
|
|
66
|
-
DEPRECATED_METHODS = [
|
67
|
-
{ deprecated: 'to_time_in_current_zone', relevant: 'in_time_zone' }
|
68
|
-
].freeze
|
64
|
+
DEPRECATED_METHODS = [{ deprecated: 'to_time_in_current_zone', relevant: 'in_time_zone' }].freeze
|
69
65
|
|
70
|
-
DEPRECATED_MSG = '`%<deprecated>s` is deprecated. '
|
71
|
-
'Use `%<relevant>s` instead.'
|
66
|
+
DEPRECATED_MSG = '`%<deprecated>s` is deprecated. Use `%<relevant>s` instead.'
|
72
67
|
|
73
68
|
def on_const(node)
|
74
69
|
mod, klass = *node.children
|
@@ -54,6 +54,7 @@ module RuboCop
|
|
54
54
|
# delegate :bar, to: :foo, prefix: true
|
55
55
|
class Delegate < Base
|
56
56
|
extend AutoCorrector
|
57
|
+
include VisibilityHelp
|
57
58
|
|
58
59
|
MSG = 'Use `delegate` to define delegations.'
|
59
60
|
|
@@ -92,15 +93,12 @@ module RuboCop
|
|
92
93
|
return false if arg_array.size != argument_array.size
|
93
94
|
|
94
95
|
arg_array.zip(argument_array).all? do |arg, argument|
|
95
|
-
arg.arg_type? &&
|
96
|
-
argument.lvar_type? &&
|
97
|
-
arg.children == argument.children
|
96
|
+
arg.arg_type? && argument.lvar_type? && arg.children == argument.children
|
98
97
|
end
|
99
98
|
end
|
100
99
|
|
101
100
|
def method_name_matches?(method_name, body)
|
102
|
-
method_name == body.method_name ||
|
103
|
-
(include_prefix_case? && method_name == prefixed_method_name(body))
|
101
|
+
method_name == body.method_name || (include_prefix_case? && method_name == prefixed_method_name(body))
|
104
102
|
end
|
105
103
|
|
106
104
|
def include_prefix_case?
|
@@ -112,17 +110,11 @@ module RuboCop
|
|
112
110
|
end
|
113
111
|
|
114
112
|
def private_or_protected_delegation(node)
|
115
|
-
|
116
|
-
private_or_protected_before(line) ||
|
117
|
-
private_or_protected_inline(line)
|
113
|
+
private_or_protected_inline(node) || node_visibility(node) != :public
|
118
114
|
end
|
119
115
|
|
120
|
-
def
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
def private_or_protected_inline(line)
|
125
|
-
processed_source[line - 1].strip.match?(/\A(private )|(protected )/)
|
116
|
+
def private_or_protected_inline(node)
|
117
|
+
processed_source[node.first_line - 1].strip.match?(/\A(private )|(protected )/)
|
126
118
|
end
|
127
119
|
end
|
128
120
|
end
|