rubocop-rails 2.8.0 → 2.10.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/LICENSE.txt +1 -1
- data/README.md +18 -2
- data/config/default.yml +101 -5
- data/config/obsoletion.yml +7 -0
- data/lib/rubocop/cop/mixin/active_record_helper.rb +16 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
- data/lib/rubocop/cop/mixin/index_method.rb +8 -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 +17 -12
- 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 +9 -2
- 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 +10 -19
- data/lib/rubocop/cop/rails/blank.rb +31 -27
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
- data/lib/rubocop/cop/rails/content_tag.rb +33 -18
- 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 +15 -12
- 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/environment_variable_access.rb +67 -0
- data/lib/rubocop/cop/rails/exit.rb +4 -10
- data/lib/rubocop/cop/rails/file_path.rb +6 -7
- 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 +19 -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 +37 -6
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +29 -3
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +32 -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 +3 -2
- data/lib/rubocop/cop/rails/index_with.rb +3 -2
- data/lib/rubocop/cop/rails/inquiry.rb +4 -3
- 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 +25 -23
- data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
- data/lib/rubocop/cop/rails/match_route.rb +14 -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 +1 -2
- 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 +7 -7
- 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 +8 -10
- 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 +17 -3
- data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
- data/lib/rubocop/cop/rails/relative_date_constant.rb +30 -21
- data/lib/rubocop/cop/rails/render_inline.rb +2 -1
- 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/require_dependency.rb +38 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +4 -8
- data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +30 -11
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
- data/lib/rubocop/cop/rails/save_bang.rb +17 -20
- 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 +5 -6
- data/lib/rubocop/cop/rails/time_zone.rb +35 -25
- data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +4 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +4 -2
- data/lib/rubocop/cop/rails/unknown_env.rb +3 -3
- 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 +19 -13
- data/lib/rubocop/cop/rails/where_not.rb +14 -19
- data/lib/rubocop/cop/rails_cops.rb +8 -0
- data/lib/rubocop/rails.rb +2 -0
- data/lib/rubocop/rails/schema_loader.rb +4 -4
- data/lib/rubocop/rails/schema_loader/schema.rb +2 -4
- data/lib/rubocop/rails/version.rb +5 -1
- metadata +29 -14
@@ -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,35 +65,25 @@ 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
|
-
(send _ :belongs_to
|
71
|
+
(send _ :belongs_to ...
|
70
72
|
(hash <$(pair (sym :required) ${true false}) ...>)
|
71
73
|
)
|
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
|
@@ -6,6 +6,10 @@ module RuboCop
|
|
6
6
|
# This cop checks for code that can be written with simpler conditionals
|
7
7
|
# using `Object#blank?` defined by Active Support.
|
8
8
|
#
|
9
|
+
# This cop is marked as unsafe auto-correction, because `' '.empty?` returns false,
|
10
|
+
# but `' '.blank?` returns true. Therefore, auto-correction is not compatible
|
11
|
+
# if the receiver is a non-empty blank string, tab, or newline meta characters.
|
12
|
+
#
|
9
13
|
# Interaction with `Style/UnlessElse`:
|
10
14
|
# The configuration of `NotPresent` will not produce an offense in the
|
11
15
|
# context of `unless else` if `Style/UnlessElse` is inabled. This is
|
@@ -53,11 +57,14 @@ module RuboCop
|
|
53
57
|
# def blank?
|
54
58
|
# !present?
|
55
59
|
# end
|
56
|
-
class Blank <
|
60
|
+
class Blank < Base
|
61
|
+
extend AutoCorrector
|
62
|
+
|
57
63
|
MSG_NIL_OR_EMPTY = 'Use `%<prefer>s` instead of `%<current>s`.'
|
58
64
|
MSG_NOT_PRESENT = 'Use `%<prefer>s` instead of `%<current>s`.'
|
59
65
|
MSG_UNLESS_PRESENT = 'Use `if %<prefer>s` instead of ' \
|
60
66
|
'`%<current>s`.'
|
67
|
+
RESTRICT_ON_SEND = %i[!].freeze
|
61
68
|
|
62
69
|
# `(send nil $_)` is not actually a valid match for an offense. Nodes
|
63
70
|
# that have a single method call on the left hand side
|
@@ -93,10 +100,10 @@ module RuboCop
|
|
93
100
|
# accepts !present? if its in the body of a `blank?` method
|
94
101
|
next if defining_blank?(node.parent)
|
95
102
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
103
|
+
message = format(MSG_NOT_PRESENT, prefer: replacement(receiver), current: node.source)
|
104
|
+
add_offense(node, message: message) do |corrector|
|
105
|
+
autocorrect(corrector, node)
|
106
|
+
end
|
100
107
|
end
|
101
108
|
end
|
102
109
|
|
@@ -106,10 +113,10 @@ module RuboCop
|
|
106
113
|
nil_or_empty?(node) do |var1, var2|
|
107
114
|
return unless var1 == var2
|
108
115
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
116
|
+
message = format(MSG_NIL_OR_EMPTY, prefer: replacement(var1), current: node.source)
|
117
|
+
add_offense(node, message: message) do |corrector|
|
118
|
+
autocorrect(corrector, node)
|
119
|
+
end
|
113
120
|
end
|
114
121
|
end
|
115
122
|
|
@@ -121,31 +128,28 @@ module RuboCop
|
|
121
128
|
unless_present?(node) do |method_call, receiver|
|
122
129
|
range = unless_condition(node, method_call)
|
123
130
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
current: range.source))
|
131
|
+
message = format(MSG_UNLESS_PRESENT, prefer: replacement(receiver), current: range.source)
|
132
|
+
add_offense(range, message: message) do |corrector|
|
133
|
+
autocorrect(corrector, node)
|
134
|
+
end
|
129
135
|
end
|
130
136
|
end
|
131
137
|
|
132
|
-
|
133
|
-
lambda do |corrector|
|
134
|
-
method_call, variable1 = unless_present?(node)
|
138
|
+
private
|
135
139
|
|
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
|
140
|
+
def autocorrect(corrector, node)
|
141
|
+
method_call, variable1 = unless_present?(node)
|
143
142
|
|
144
|
-
|
143
|
+
if method_call
|
144
|
+
corrector.replace(node.loc.keyword, 'if')
|
145
|
+
range = method_call.loc.expression
|
146
|
+
else
|
147
|
+
variable1, _variable2 = nil_or_empty?(node) || not_present?(node)
|
148
|
+
range = node.loc.expression
|
145
149
|
end
|
146
|
-
end
|
147
150
|
|
148
|
-
|
151
|
+
corrector.replace(range, replacement(variable1))
|
152
|
+
end
|
149
153
|
|
150
154
|
def unless_condition(node, method_call)
|
151
155
|
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,42 +18,57 @@ 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
|
-
def
|
30
|
-
|
31
|
+
def on_new_investigation
|
32
|
+
@corrected_nodes = nil
|
33
|
+
end
|
31
34
|
|
35
|
+
def on_send(node)
|
32
36
|
first_argument = node.first_argument
|
33
|
-
return
|
37
|
+
return if !first_argument ||
|
38
|
+
allowed_argument?(first_argument) ||
|
39
|
+
corrected_ancestor?(node)
|
40
|
+
|
41
|
+
add_offense(node) do |corrector|
|
42
|
+
autocorrect(corrector, node)
|
43
|
+
|
44
|
+
@corrected_nodes ||= Set.new.compare_by_identity
|
45
|
+
@corrected_nodes.add(node)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
34
50
|
|
35
|
-
|
51
|
+
def corrected_ancestor?(node)
|
52
|
+
node.each_ancestor(:send).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
|
53
|
+
end
|
36
54
|
|
37
|
-
|
55
|
+
def allowed_argument?(argument)
|
56
|
+
argument.variable? || argument.send_type? || argument.const_type? || argument.splat_type?
|
38
57
|
end
|
39
58
|
|
40
|
-
def autocorrect(node)
|
41
|
-
|
42
|
-
|
43
|
-
range = correction_range(node)
|
59
|
+
def autocorrect(corrector, node)
|
60
|
+
if method_name?(node.first_argument)
|
61
|
+
range = correction_range(node)
|
44
62
|
|
45
|
-
|
46
|
-
|
63
|
+
rest_args = node.arguments.drop(1)
|
64
|
+
replacement = "tag.#{node.first_argument.value.to_s.underscore}(#{rest_args.map(&:source).join(', ')})"
|
47
65
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
66
|
+
corrector.replace(range, replacement)
|
67
|
+
else
|
68
|
+
corrector.replace(node.loc.selector, 'tag')
|
52
69
|
end
|
53
70
|
end
|
54
71
|
|
55
|
-
private
|
56
|
-
|
57
72
|
def method_name?(node)
|
58
73
|
return false unless node.str_type? || node.sym_type?
|
59
74
|
|
@@ -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,36 +31,39 @@ 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
|
+
include ActiveRecordHelper
|
36
|
+
extend AutoCorrector
|
37
|
+
|
35
38
|
MSG = 'Use `%<static_name>s` instead of dynamic `%<method>s`.'
|
36
39
|
METHOD_PATTERN = /^find_by_(.+?)(!)?$/.freeze
|
37
40
|
|
38
41
|
def on_send(node)
|
39
|
-
return if allowed_invocation?(node)
|
42
|
+
return if node.receiver.nil? && !inherit_active_record_base?(node) || allowed_invocation?(node)
|
40
43
|
|
41
44
|
method_name = node.method_name
|
42
45
|
static_name = static_method_name(method_name)
|
43
46
|
return unless static_name
|
47
|
+
return if node.arguments.any?(&:splat_type?)
|
44
48
|
|
45
|
-
|
46
|
-
|
47
|
-
|
49
|
+
message = format(MSG, static_name: static_name, method: method_name)
|
50
|
+
add_offense(node, message: message) do |corrector|
|
51
|
+
autocorrect(corrector, node)
|
52
|
+
end
|
48
53
|
end
|
49
54
|
alias on_csend on_send
|
50
55
|
|
51
|
-
|
56
|
+
private
|
57
|
+
|
58
|
+
def autocorrect(corrector, node)
|
52
59
|
keywords = column_keywords(node.method_name)
|
53
60
|
|
54
61
|
return if keywords.size != node.arguments.size
|
55
62
|
|
56
|
-
|
57
|
-
|
58
|
-
autocorrect_argument_keywords(corrector, node, keywords)
|
59
|
-
end
|
63
|
+
autocorrect_method_name(corrector, node)
|
64
|
+
autocorrect_argument_keywords(corrector, node, keywords)
|
60
65
|
end
|
61
66
|
|
62
|
-
private
|
63
|
-
|
64
67
|
def allowed_invocation?(node)
|
65
68
|
allowed_method?(node) || allowed_receiver?(node) ||
|
66
69
|
whitelisted?(node)
|