rubocop-rails 2.7.0 → 2.9.1
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/README.md +16 -0
- data/config/default.yml +78 -4
- data/lib/rubocop/cop/mixin/active_record_helper.rb +5 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
- data/lib/rubocop/cop/mixin/index_method.rb +25 -11
- data/lib/rubocop/cop/rails/action_filter.rb +10 -14
- data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +19 -16
- data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
- data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
- data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
- data/lib/rubocop/cop/rails/application_controller.rb +3 -7
- data/lib/rubocop/cop/rails/application_job.rb +2 -1
- data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
- data/lib/rubocop/cop/rails/application_record.rb +2 -7
- data/lib/rubocop/cop/rails/arel_star.rb +41 -0
- data/lib/rubocop/cop/rails/assert_not.rb +8 -10
- data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
- data/lib/rubocop/cop/rails/belongs_to.rb +9 -18
- data/lib/rubocop/cop/rails/blank.rb +27 -27
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
- data/lib/rubocop/cop/rails/content_tag.rb +17 -17
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
- data/lib/rubocop/cop/rails/date.rb +10 -11
- data/lib/rubocop/cop/rails/default_scope.rb +11 -4
- data/lib/rubocop/cop/rails/delegate.rb +9 -9
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +13 -11
- data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
- data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
- data/lib/rubocop/cop/rails/exit.rb +4 -10
- data/lib/rubocop/cop/rails/file_path.rb +5 -4
- data/lib/rubocop/cop/rails/find_by.rb +13 -13
- data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
- data/lib/rubocop/cop/rails/find_each.rb +17 -18
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +4 -7
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +30 -2
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +25 -21
- data/lib/rubocop/cop/rails/http_status.rb +7 -9
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
- data/lib/rubocop/cop/rails/index_by.rb +11 -2
- data/lib/rubocop/cop/rails/index_with.rb +11 -2
- data/lib/rubocop/cop/rails/inquiry.rb +7 -2
- data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
- data/lib/rubocop/cop/rails/link_to_blank.rb +20 -22
- data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
- data/lib/rubocop/cop/rails/match_route.rb +16 -13
- data/lib/rubocop/cop/rails/negate_include.rb +10 -8
- data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
- data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
- data/lib/rubocop/cop/rails/output.rb +5 -2
- data/lib/rubocop/cop/rails/output_safety.rb +3 -2
- data/lib/rubocop/cop/rails/pick.rb +14 -12
- data/lib/rubocop/cop/rails/pluck.rb +6 -9
- data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
- data/lib/rubocop/cop/rails/pluck_in_where.rb +39 -5
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
- data/lib/rubocop/cop/rails/presence.rb +12 -13
- data/lib/rubocop/cop/rails/present.rb +30 -24
- data/lib/rubocop/cop/rails/rake_environment.rb +9 -11
- data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
- data/lib/rubocop/cop/rails/reflection_class_name.rb +4 -3
- data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
- data/lib/rubocop/cop/rails/relative_date_constant.rb +20 -9
- data/lib/rubocop/cop/rails/render_inline.rb +5 -12
- data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
- data/lib/rubocop/cop/rails/request_referer.rb +7 -7
- data/lib/rubocop/cop/rails/reversible_migration.rb +82 -7
- data/lib/rubocop/cop/rails/safe_navigation.rb +11 -10
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
- data/lib/rubocop/cop/rails/save_bang.rb +19 -22
- data/lib/rubocop/cop/rails/scope_args.rb +2 -1
- data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
- data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
- data/lib/rubocop/cop/rails/time_zone.rb +22 -20
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +6 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
- data/lib/rubocop/cop/rails/unknown_env.rb +15 -4
- data/lib/rubocop/cop/rails/validation.rb +15 -14
- data/lib/rubocop/cop/rails/where_equals.rb +98 -0
- data/lib/rubocop/cop/rails/where_exists.rb +74 -16
- data/lib/rubocop/cop/rails/where_not.rb +97 -0
- data/lib/rubocop/cop/rails_cops.rb +8 -0
- data/lib/rubocop/rails/schema_loader.rb +4 -4
- data/lib/rubocop/rails/schema_loader/schema.rb +5 -5
- data/lib/rubocop/rails/version.rb +5 -1
- metadata +23 -9
@@ -50,7 +50,8 @@ module RuboCop
|
|
50
50
|
#
|
51
51
|
# @see https://guides.rubyonrails.org/5_0_release_notes.html
|
52
52
|
# @see https://github.com/rails/rails/pull/18937
|
53
|
-
class BelongsTo <
|
53
|
+
class BelongsTo < Base
|
54
|
+
extend AutoCorrector
|
54
55
|
extend TargetRailsVersion
|
55
56
|
|
56
57
|
minimum_target_rails_version 5.0
|
@@ -64,6 +65,7 @@ module RuboCop
|
|
64
65
|
'option is deprecated and you want to use `optional: false`. ' \
|
65
66
|
'In most configurations, this is the default and you can omit ' \
|
66
67
|
'this option altogether'
|
68
|
+
RESTRICT_ON_SEND = %i[belongs_to].freeze
|
67
69
|
|
68
70
|
def_node_matcher :match_belongs_to_with_options, <<~PATTERN
|
69
71
|
(send _ :belongs_to _
|
@@ -72,27 +74,16 @@ module RuboCop
|
|
72
74
|
PATTERN
|
73
75
|
|
74
76
|
def on_send(node)
|
75
|
-
match_belongs_to_with_options(node) do |
|
76
|
-
message =
|
77
|
+
match_belongs_to_with_options(node) do |option_node, option_value|
|
78
|
+
message, replacement =
|
77
79
|
if option_value.true_type?
|
78
|
-
SUPERFLOUS_REQUIRE_TRUE_MSG
|
80
|
+
[SUPERFLOUS_REQUIRE_TRUE_MSG, 'optional: false']
|
79
81
|
elsif option_value.false_type?
|
80
|
-
SUPERFLOUS_REQUIRE_FALSE_MSG
|
82
|
+
[SUPERFLOUS_REQUIRE_FALSE_MSG, 'optional: true']
|
81
83
|
end
|
82
84
|
|
83
|
-
add_offense(node, message: message
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
def autocorrect(node)
|
88
|
-
option_node, option_value = match_belongs_to_with_options(node)
|
89
|
-
return unless option_node
|
90
|
-
|
91
|
-
lambda do |corrector|
|
92
|
-
if option_value.true_type?
|
93
|
-
corrector.replace(option_node.loc.expression, 'optional: false')
|
94
|
-
elsif option_value.false_type?
|
95
|
-
corrector.replace(option_node.loc.expression, 'optional: true')
|
85
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
86
|
+
corrector.replace(option_node.loc.expression, replacement)
|
96
87
|
end
|
97
88
|
end
|
98
89
|
end
|
@@ -53,11 +53,14 @@ module RuboCop
|
|
53
53
|
# def blank?
|
54
54
|
# !present?
|
55
55
|
# end
|
56
|
-
class Blank <
|
56
|
+
class Blank < Base
|
57
|
+
extend AutoCorrector
|
58
|
+
|
57
59
|
MSG_NIL_OR_EMPTY = 'Use `%<prefer>s` instead of `%<current>s`.'
|
58
60
|
MSG_NOT_PRESENT = 'Use `%<prefer>s` instead of `%<current>s`.'
|
59
61
|
MSG_UNLESS_PRESENT = 'Use `if %<prefer>s` instead of ' \
|
60
62
|
'`%<current>s`.'
|
63
|
+
RESTRICT_ON_SEND = %i[!].freeze
|
61
64
|
|
62
65
|
# `(send nil $_)` is not actually a valid match for an offense. Nodes
|
63
66
|
# that have a single method call on the left hand side
|
@@ -93,10 +96,10 @@ module RuboCop
|
|
93
96
|
# accepts !present? if its in the body of a `blank?` method
|
94
97
|
next if defining_blank?(node.parent)
|
95
98
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
99
|
+
message = format(MSG_NOT_PRESENT, prefer: replacement(receiver), current: node.source)
|
100
|
+
add_offense(node, message: message) do |corrector|
|
101
|
+
autocorrect(corrector, node)
|
102
|
+
end
|
100
103
|
end
|
101
104
|
end
|
102
105
|
|
@@ -106,10 +109,10 @@ module RuboCop
|
|
106
109
|
nil_or_empty?(node) do |var1, var2|
|
107
110
|
return unless var1 == var2
|
108
111
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
112
|
+
message = format(MSG_NIL_OR_EMPTY, prefer: replacement(var1), current: node.source)
|
113
|
+
add_offense(node, message: message) do |corrector|
|
114
|
+
autocorrect(corrector, node)
|
115
|
+
end
|
113
116
|
end
|
114
117
|
end
|
115
118
|
|
@@ -121,31 +124,28 @@ module RuboCop
|
|
121
124
|
unless_present?(node) do |method_call, receiver|
|
122
125
|
range = unless_condition(node, method_call)
|
123
126
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
current: range.source))
|
127
|
+
message = format(MSG_UNLESS_PRESENT, prefer: replacement(receiver), current: range.source)
|
128
|
+
add_offense(range, message: message) do |corrector|
|
129
|
+
autocorrect(corrector, node)
|
130
|
+
end
|
129
131
|
end
|
130
132
|
end
|
131
133
|
|
132
|
-
|
133
|
-
lambda do |corrector|
|
134
|
-
method_call, variable1 = unless_present?(node)
|
134
|
+
private
|
135
135
|
|
136
|
-
|
137
|
-
|
138
|
-
range = method_call.loc.expression
|
139
|
-
else
|
140
|
-
variable1, _variable2 = nil_or_empty?(node) || not_present?(node)
|
141
|
-
range = node.loc.expression
|
142
|
-
end
|
136
|
+
def autocorrect(corrector, node)
|
137
|
+
method_call, variable1 = unless_present?(node)
|
143
138
|
|
144
|
-
|
139
|
+
if method_call
|
140
|
+
corrector.replace(node.loc.keyword, 'if')
|
141
|
+
range = method_call.loc.expression
|
142
|
+
else
|
143
|
+
variable1, _variable2 = nil_or_empty?(node) || not_present?(node)
|
144
|
+
range = node.loc.expression
|
145
145
|
end
|
146
|
-
end
|
147
146
|
|
148
|
-
|
147
|
+
corrector.replace(range, replacement(variable1))
|
148
|
+
end
|
149
149
|
|
150
150
|
def unless_condition(node, method_call)
|
151
151
|
if node.modifier_form?
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
#
|
66
66
|
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-change_table
|
67
67
|
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
|
68
|
-
class BulkChangeTable <
|
68
|
+
class BulkChangeTable < Base
|
69
69
|
MSG_FOR_CHANGE_TABLE = <<~MSG.chomp
|
70
70
|
You can combine alter queries using `bulk: true` options.
|
71
71
|
MSG
|
@@ -18,46 +18,46 @@ module RuboCop
|
|
18
18
|
# tag.p('Hello world!')
|
19
19
|
# tag.br
|
20
20
|
# content_tag(name, 'Hello world!')
|
21
|
-
class ContentTag <
|
21
|
+
class ContentTag < Base
|
22
22
|
include RangeHelp
|
23
|
+
extend AutoCorrector
|
23
24
|
extend TargetRailsVersion
|
24
25
|
|
25
26
|
minimum_target_rails_version 5.1
|
26
27
|
|
27
28
|
MSG = 'Use `tag` instead of `content_tag`.'
|
29
|
+
RESTRICT_ON_SEND = %i[content_tag].freeze
|
28
30
|
|
29
31
|
def on_send(node)
|
30
|
-
return unless node.method?(:content_tag)
|
31
|
-
|
32
32
|
first_argument = node.first_argument
|
33
33
|
return unless first_argument
|
34
34
|
|
35
35
|
return if first_argument.variable? || first_argument.send_type? || first_argument.const_type?
|
36
36
|
|
37
|
-
add_offense(node)
|
37
|
+
add_offense(node) do |corrector|
|
38
|
+
autocorrect(corrector, node)
|
39
|
+
end
|
38
40
|
end
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
private
|
43
|
+
|
44
|
+
def autocorrect(corrector, node)
|
45
|
+
if method_name?(node.first_argument)
|
46
|
+
range = correction_range(node)
|
44
47
|
|
45
|
-
|
46
|
-
|
48
|
+
rest_args = node.arguments.drop(1)
|
49
|
+
replacement = "tag.#{node.first_argument.value.to_s.underscore}(#{rest_args.map(&:source).join(', ')})"
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
51
|
+
corrector.replace(range, replacement)
|
52
|
+
else
|
53
|
+
corrector.replace(node.loc.selector, 'tag')
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
|
-
private
|
56
|
-
|
57
57
|
def method_name?(node)
|
58
58
|
return false unless node.str_type? || node.sym_type?
|
59
59
|
|
60
|
-
/^[a-zA-Z_][a-zA-
|
60
|
+
/^[a-zA-Z_][a-zA-Z_\-0-9]*$/.match?(node.value)
|
61
61
|
end
|
62
62
|
|
63
63
|
def correction_range(node)
|
@@ -40,8 +40,9 @@ module RuboCop
|
|
40
40
|
#
|
41
41
|
# t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP' }
|
42
42
|
# end
|
43
|
-
class CreateTableWithTimestamps <
|
43
|
+
class CreateTableWithTimestamps < Base
|
44
44
|
MSG = 'Add timestamps when creating a new table.'
|
45
|
+
RESTRICT_ON_SEND = %i[create_table].freeze
|
45
46
|
|
46
47
|
def_node_matcher :create_table_with_block?, <<~PATTERN
|
47
48
|
(block
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
# Date.yesterday
|
44
44
|
# date.in_time_zone
|
45
45
|
#
|
46
|
-
class Date <
|
46
|
+
class Date < Base
|
47
47
|
include ConfigurableEnforcedStyle
|
48
48
|
|
49
49
|
MSG = 'Do not use `Date.%<method_called>s` without zone. Use ' \
|
@@ -52,6 +52,8 @@ module RuboCop
|
|
52
52
|
MSG_SEND = 'Do not use `%<method>s` on Date objects, because they ' \
|
53
53
|
'know nothing about the time zone in use.'
|
54
54
|
|
55
|
+
RESTRICT_ON_SEND = %i[to_time to_time_in_current_zone].freeze
|
56
|
+
|
55
57
|
BAD_DAYS = %i[today current yesterday tomorrow].freeze
|
56
58
|
|
57
59
|
DEPRECATED_METHODS = [
|
@@ -76,8 +78,7 @@ module RuboCop
|
|
76
78
|
|
77
79
|
check_deprecated_methods(node)
|
78
80
|
|
79
|
-
add_offense(node,
|
80
|
-
message: format(MSG_SEND, method: node.method_name))
|
81
|
+
add_offense(node.loc.selector, message: format(MSG_SEND, method: node.method_name))
|
81
82
|
end
|
82
83
|
alias on_csend on_send
|
83
84
|
|
@@ -87,10 +88,9 @@ module RuboCop
|
|
87
88
|
DEPRECATED_METHODS.each do |method|
|
88
89
|
next unless node.method?(method[:deprecated].to_sym)
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
relevant: method[:relevant]))
|
91
|
+
message = format(DEPRECATED_MSG, deprecated: method[:deprecated], relevant: method[:relevant])
|
92
|
+
|
93
|
+
add_offense(node.loc.selector, message: message)
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
@@ -104,10 +104,9 @@ module RuboCop
|
|
104
104
|
day = method_name
|
105
105
|
day = 'today' if method_name == 'current'
|
106
106
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
day: day))
|
107
|
+
message = format(MSG, method_called: method_name, day: day)
|
108
|
+
|
109
|
+
add_offense(node.loc.selector, message: message)
|
111
110
|
end
|
112
111
|
|
113
112
|
def extract_method_chain(node)
|
@@ -22,8 +22,9 @@ module RuboCop
|
|
22
22
|
# where(hidden: false)
|
23
23
|
# end
|
24
24
|
#
|
25
|
-
class DefaultScope <
|
25
|
+
class DefaultScope < Base
|
26
26
|
MSG = 'Avoid use of `default_scope`. It is better to use explicitly named scopes.'
|
27
|
+
RESTRICT_ON_SEND = %i[default_scope].freeze
|
27
28
|
|
28
29
|
def_node_matcher :method_call?, <<~PATTERN
|
29
30
|
(send nil? :default_scope ...)
|
@@ -38,15 +39,21 @@ module RuboCop
|
|
38
39
|
PATTERN
|
39
40
|
|
40
41
|
def on_send(node)
|
41
|
-
|
42
|
+
return unless method_call?(node)
|
43
|
+
|
44
|
+
add_offense(node.loc.selector)
|
42
45
|
end
|
43
46
|
|
44
47
|
def on_defs(node)
|
45
|
-
|
48
|
+
return unless class_method_definition?(node)
|
49
|
+
|
50
|
+
add_offense(node.loc.name)
|
46
51
|
end
|
47
52
|
|
48
53
|
def on_sclass(node)
|
49
|
-
eigenclass_method_definition?(node)
|
54
|
+
eigenclass_method_definition?(node) do |default_scope|
|
55
|
+
add_offense(default_scope.loc.name)
|
56
|
+
end
|
50
57
|
end
|
51
58
|
end
|
52
59
|
end
|
@@ -52,7 +52,9 @@ module RuboCop
|
|
52
52
|
#
|
53
53
|
# # good
|
54
54
|
# delegate :bar, to: :foo, prefix: true
|
55
|
-
class Delegate <
|
55
|
+
class Delegate < Base
|
56
|
+
extend AutoCorrector
|
57
|
+
|
56
58
|
MSG = 'Use `delegate` to define delegations.'
|
57
59
|
|
58
60
|
def_node_matcher :delegate?, <<~PATTERN
|
@@ -64,22 +66,20 @@ module RuboCop
|
|
64
66
|
return unless trivial_delegate?(node)
|
65
67
|
return if private_or_protected_delegation(node)
|
66
68
|
|
67
|
-
|
69
|
+
register_offense(node)
|
68
70
|
end
|
69
71
|
|
70
|
-
|
71
|
-
delegation = ["delegate :#{node.body.method_name}",
|
72
|
-
"to: :#{node.body.receiver.method_name}"]
|
72
|
+
private
|
73
73
|
|
74
|
-
|
74
|
+
def register_offense(node)
|
75
|
+
add_offense(node.loc.keyword) do |corrector|
|
76
|
+
delegation = ["delegate :#{node.body.method_name}", "to: :#{node.body.receiver.method_name}"]
|
77
|
+
delegation << ['prefix: true'] if node.method?(prefixed_method_name(node.body))
|
75
78
|
|
76
|
-
lambda do |corrector|
|
77
79
|
corrector.replace(node.source_range, delegation.join(', '))
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
81
|
-
private
|
82
|
-
|
83
83
|
def trivial_delegate?(def_node)
|
84
84
|
delegate?(def_node) &&
|
85
85
|
method_name_matches?(def_node.method_name, def_node.body) &&
|
@@ -13,22 +13,21 @@ module RuboCop
|
|
13
13
|
#
|
14
14
|
# # good
|
15
15
|
# delegate :foo, to: :bar, allow_nil: true
|
16
|
-
class DelegateAllowBlank <
|
16
|
+
class DelegateAllowBlank < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
17
19
|
MSG = '`allow_blank` is not a valid option, use `allow_nil`.'
|
20
|
+
RESTRICT_ON_SEND = %i[delegate].freeze
|
18
21
|
|
19
22
|
def_node_matcher :allow_blank_option, <<~PATTERN
|
20
23
|
(send nil? :delegate _ (hash <$(pair (sym :allow_blank) true) ...>))
|
21
24
|
PATTERN
|
22
25
|
|
23
26
|
def on_send(node)
|
24
|
-
allow_blank_option(node)
|
25
|
-
add_offense(offending_node)
|
26
|
-
end
|
27
|
-
end
|
27
|
+
return unless (offending_node = allow_blank_option(node))
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
corrector.replace(pair_node.key.source_range, 'allow_nil')
|
29
|
+
add_offense(offending_node) do |corrector|
|
30
|
+
corrector.replace(offending_node.key.source_range, 'allow_nil')
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
@@ -31,7 +31,9 @@ module RuboCop
|
|
31
31
|
#
|
32
32
|
# # good
|
33
33
|
# Gem::Specification.find_by_name('backend').gem_dir
|
34
|
-
class DynamicFindBy <
|
34
|
+
class DynamicFindBy < Base
|
35
|
+
extend AutoCorrector
|
36
|
+
|
35
37
|
MSG = 'Use `%<static_name>s` instead of dynamic `%<method>s`.'
|
36
38
|
METHOD_PATTERN = /^find_by_(.+?)(!)?$/.freeze
|
37
39
|
|
@@ -41,26 +43,26 @@ module RuboCop
|
|
41
43
|
method_name = node.method_name
|
42
44
|
static_name = static_method_name(method_name)
|
43
45
|
return unless static_name
|
46
|
+
return if node.arguments.any?(&:splat_type?)
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
message = format(MSG, static_name: static_name, method: method_name)
|
49
|
+
add_offense(node, message: message) do |corrector|
|
50
|
+
autocorrect(corrector, node)
|
51
|
+
end
|
48
52
|
end
|
49
53
|
alias on_csend on_send
|
50
54
|
|
51
|
-
|
55
|
+
private
|
56
|
+
|
57
|
+
def autocorrect(corrector, node)
|
52
58
|
keywords = column_keywords(node.method_name)
|
53
59
|
|
54
60
|
return if keywords.size != node.arguments.size
|
55
61
|
|
56
|
-
|
57
|
-
|
58
|
-
autocorrect_argument_keywords(corrector, node, keywords)
|
59
|
-
end
|
62
|
+
autocorrect_method_name(corrector, node)
|
63
|
+
autocorrect_argument_keywords(corrector, node, keywords)
|
60
64
|
end
|
61
65
|
|
62
|
-
private
|
63
|
-
|
64
66
|
def allowed_invocation?(node)
|
65
67
|
allowed_method?(node) || allowed_receiver?(node) ||
|
66
68
|
whitelisted?(node)
|
@@ -17,9 +17,12 @@ module RuboCop
|
|
17
17
|
# # good
|
18
18
|
# enum status: { active: 0, archived: 1 }
|
19
19
|
#
|
20
|
-
class EnumHash <
|
20
|
+
class EnumHash < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
21
23
|
MSG = 'Enum defined as an array found in `%<enum>s` enum declaration. '\
|
22
24
|
'Use hash syntax instead.'
|
25
|
+
RESTRICT_ON_SEND = %i[enum].freeze
|
23
26
|
|
24
27
|
def_node_matcher :enum?, <<~PATTERN
|
25
28
|
(send nil? :enum (hash $...))
|
@@ -35,19 +38,17 @@ module RuboCop
|
|
35
38
|
key, array = array_pair?(pair)
|
36
39
|
next unless key
|
37
40
|
|
38
|
-
add_offense(array, message: format(MSG, enum: enum_name(key)))
|
41
|
+
add_offense(array, message: format(MSG, enum: enum_name(key))) do |corrector|
|
42
|
+
hash = array.children.each_with_index.map do |elem, index|
|
43
|
+
"#{source(elem)} => #{index}"
|
44
|
+
end.join(', ')
|
45
|
+
|
46
|
+
corrector.replace(array.loc.expression, "{#{hash}}")
|
47
|
+
end
|
39
48
|
end
|
40
49
|
end
|
41
50
|
end
|
42
51
|
|
43
|
-
def autocorrect(node)
|
44
|
-
hash = node.children.each_with_index.map do |elem, index|
|
45
|
-
"#{source(elem)} => #{index}"
|
46
|
-
end.join(', ')
|
47
|
-
|
48
|
-
->(corrector) { corrector.replace(node.loc.expression, "{#{hash}}") }
|
49
|
-
end
|
50
|
-
|
51
52
|
private
|
52
53
|
|
53
54
|
def enum_name(key)
|