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
@@ -31,8 +31,11 @@ module RuboCop
|
|
31
31
|
# render plain: 'foo/bar', status: 304
|
32
32
|
# redirect_to root_url, status: 301
|
33
33
|
#
|
34
|
-
class HttpStatus <
|
34
|
+
class HttpStatus < Base
|
35
35
|
include ConfigurableEnforcedStyle
|
36
|
+
extend AutoCorrector
|
37
|
+
|
38
|
+
RESTRICT_ON_SEND = %i[render redirect_to].freeze
|
36
39
|
|
37
40
|
def_node_matcher :http_status, <<~PATTERN
|
38
41
|
{
|
@@ -53,14 +56,9 @@ module RuboCop
|
|
53
56
|
checker = checker_class.new(status)
|
54
57
|
return unless checker.offensive?
|
55
58
|
|
56
|
-
add_offense(checker.node, message: checker.message)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
def autocorrect(node)
|
61
|
-
lambda do |corrector|
|
62
|
-
checker = checker_class.new(node)
|
63
|
-
corrector.replace(node.loc.expression, checker.preferred_style)
|
59
|
+
add_offense(checker.node, message: checker.message) do |corrector|
|
60
|
+
corrector.replace(checker.node.loc.expression, checker.preferred_style)
|
61
|
+
end
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
@@ -37,18 +37,20 @@ module RuboCop
|
|
37
37
|
# end
|
38
38
|
#
|
39
39
|
# @see https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options
|
40
|
-
class IgnoredSkipActionFilterOption <
|
40
|
+
class IgnoredSkipActionFilterOption < Base
|
41
41
|
MSG = <<~MSG.chomp.freeze
|
42
42
|
`%<ignore>s` option will be ignored when `%<prefer>s` and `%<ignore>s` are used together.
|
43
43
|
MSG
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
RESTRICT_ON_SEND = %i[
|
46
|
+
skip_after_action
|
47
|
+
skip_around_action
|
48
|
+
skip_before_action
|
49
|
+
skip_action_callback
|
50
50
|
].freeze
|
51
51
|
|
52
|
+
FILTERS = RESTRICT_ON_SEND.map { |method_name| ":#{method_name}" }
|
53
|
+
|
52
54
|
def_node_matcher :filter_options, <<~PATTERN
|
53
55
|
(send
|
54
56
|
nil?
|
@@ -11,19 +11,28 @@ module RuboCop
|
|
11
11
|
# @example
|
12
12
|
# # bad
|
13
13
|
# [1, 2, 3].each_with_object({}) { |el, h| h[foo(el)] = el }
|
14
|
+
# [1, 2, 3].to_h { |el| [foo(el), el] }
|
14
15
|
# [1, 2, 3].map { |el| [foo(el), el] }.to_h
|
15
16
|
# Hash[[1, 2, 3].collect { |el| [foo(el), el] }]
|
16
17
|
#
|
17
18
|
# # good
|
18
19
|
# [1, 2, 3].index_by { |el| foo(el) }
|
19
|
-
class IndexBy <
|
20
|
+
class IndexBy < Base
|
20
21
|
include IndexMethod
|
22
|
+
extend AutoCorrector
|
21
23
|
|
22
24
|
def_node_matcher :on_bad_each_with_object, <<~PATTERN
|
23
25
|
(block
|
24
26
|
({send csend} _ :each_with_object (hash))
|
25
27
|
(args (arg $_el) (arg _memo))
|
26
|
-
({send csend} (lvar _memo) :[]=
|
28
|
+
({send csend} (lvar _memo) :[]= $!`_memo (lvar _el)))
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def_node_matcher :on_bad_to_h, <<~PATTERN
|
32
|
+
(block
|
33
|
+
({send csend} _ :to_h)
|
34
|
+
(args (arg $_el))
|
35
|
+
(array $_ (lvar _el)))
|
27
36
|
PATTERN
|
28
37
|
|
29
38
|
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
@@ -11,12 +11,14 @@ module RuboCop
|
|
11
11
|
# @example
|
12
12
|
# # bad
|
13
13
|
# [1, 2, 3].each_with_object({}) { |el, h| h[el] = foo(el) }
|
14
|
+
# [1, 2, 3].to_h { |el| [el, foo(el)] }
|
14
15
|
# [1, 2, 3].map { |el| [el, foo(el)] }.to_h
|
15
16
|
# Hash[[1, 2, 3].collect { |el| [el, foo(el)] }]
|
16
17
|
#
|
17
18
|
# # good
|
18
19
|
# [1, 2, 3].index_with { |el| foo(el) }
|
19
|
-
class IndexWith <
|
20
|
+
class IndexWith < Base
|
21
|
+
extend AutoCorrector
|
20
22
|
extend TargetRailsVersion
|
21
23
|
include IndexMethod
|
22
24
|
|
@@ -26,7 +28,14 @@ module RuboCop
|
|
26
28
|
(block
|
27
29
|
({send csend} _ :each_with_object (hash))
|
28
30
|
(args (arg $_el) (arg _memo))
|
29
|
-
({send csend} (lvar _memo) :[]= (lvar _el)
|
31
|
+
({send csend} (lvar _memo) :[]= (lvar _el) $!`_memo))
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def_node_matcher :on_bad_to_h, <<~PATTERN
|
35
|
+
(block
|
36
|
+
({send csend} _ :to_h)
|
37
|
+
(args (arg $_el))
|
38
|
+
(array (lvar _el) $_))
|
30
39
|
PATTERN
|
31
40
|
|
32
41
|
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
@@ -22,11 +22,16 @@ module RuboCop
|
|
22
22
|
# pets = %w(cat dog)
|
23
23
|
# pets.include? 'cat'
|
24
24
|
#
|
25
|
-
class Inquiry <
|
25
|
+
class Inquiry < Base
|
26
26
|
MSG = "Prefer Ruby's comparison operators over Active Support's `inquiry`."
|
27
|
+
RESTRICT_ON_SEND = %i[inquiry].freeze
|
27
28
|
|
28
29
|
def on_send(node)
|
29
|
-
|
30
|
+
return unless node.arguments.empty?
|
31
|
+
return unless (receiver = node.receiver)
|
32
|
+
return if !receiver.str_type? && !receiver.array_type?
|
33
|
+
|
34
|
+
add_offense(node.loc.selector)
|
30
35
|
end
|
31
36
|
end
|
32
37
|
end
|
@@ -128,10 +128,11 @@ module RuboCop
|
|
128
128
|
#
|
129
129
|
# @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
|
130
130
|
# @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
|
131
|
-
class InverseOf <
|
131
|
+
class InverseOf < Base
|
132
132
|
SPECIFY_MSG = 'Specify an `:inverse_of` option.'
|
133
133
|
NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to ' \
|
134
134
|
'use `inverse_of: false`.'
|
135
|
+
RESTRICT_ON_SEND = %i[has_many has_one belongs_to].freeze
|
135
136
|
|
136
137
|
def_node_matcher :association_recv_arguments, <<~PATTERN
|
137
138
|
(send $_ {:has_many :has_one :belongs_to} _ $...)
|
@@ -185,7 +186,7 @@ module RuboCop
|
|
185
186
|
|
186
187
|
return if options_contain_inverse_of?(options)
|
187
188
|
|
188
|
-
add_offense(node, message: message(options)
|
189
|
+
add_offense(node.loc.selector, message: message(options))
|
189
190
|
end
|
190
191
|
|
191
192
|
def scope?(arguments)
|
@@ -82,25 +82,27 @@ module RuboCop
|
|
82
82
|
# @content = Article.find(params[:article_id])
|
83
83
|
# end
|
84
84
|
# end
|
85
|
-
class LexicallyScopedActionFilter <
|
85
|
+
class LexicallyScopedActionFilter < Base
|
86
86
|
MSG = '%<action>s not explicitly defined on the %<type>s.'
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
88
|
+
RESTRICT_ON_SEND = %i[
|
89
|
+
after_action
|
90
|
+
append_after_action
|
91
|
+
append_around_action
|
92
|
+
append_before_action
|
93
|
+
around_action
|
94
|
+
before_action
|
95
|
+
prepend_after_action
|
96
|
+
prepend_around_action
|
97
|
+
prepend_before_action
|
98
|
+
skip_after_action
|
99
|
+
skip_around_action
|
100
|
+
skip_before_action
|
101
|
+
skip_action_callback
|
102
102
|
].freeze
|
103
103
|
|
104
|
+
FILTERS = RESTRICT_ON_SEND.map { |method_name| ":#{method_name}" }
|
105
|
+
|
104
106
|
def_node_matcher :only_or_except_filter_methods, <<~PATTERN
|
105
107
|
(send
|
106
108
|
nil?
|
@@ -20,8 +20,11 @@ module RuboCop
|
|
20
20
|
#
|
21
21
|
# # good
|
22
22
|
# link_to 'Click here', url, target: '_blank', rel: 'noreferrer'
|
23
|
-
class LinkToBlank <
|
23
|
+
class LinkToBlank < Base
|
24
|
+
extend AutoCorrector
|
25
|
+
|
24
26
|
MSG = 'Specify a `:rel` option containing noopener.'
|
27
|
+
RESTRICT_ON_SEND = %i[link_to].freeze
|
25
28
|
|
26
29
|
def_node_matcher :blank_target?, <<~PATTERN
|
27
30
|
(pair {(sym :target) (str "target")} {(str "_blank") (sym :_blank)})
|
@@ -35,39 +38,34 @@ module RuboCop
|
|
35
38
|
(pair {(sym :rel) (str "rel")} (str _))
|
36
39
|
PATTERN
|
37
40
|
|
38
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
39
41
|
def on_send(node)
|
40
|
-
return unless node.method?(:link_to)
|
41
|
-
|
42
42
|
option_nodes = node.each_child_node(:hash)
|
43
43
|
|
44
44
|
option_nodes.map(&:children).each do |options|
|
45
45
|
blank = options.find { |o| blank_target?(o) }
|
46
|
-
|
46
|
+
next unless blank && options.none? { |o| includes_noopener?(o) }
|
47
|
+
|
48
|
+
add_offense(blank) do |corrector|
|
49
|
+
autocorrect(corrector, node, blank, option_nodes)
|
50
|
+
end
|
47
51
|
end
|
48
52
|
end
|
49
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
50
53
|
|
51
|
-
|
52
|
-
lambda do |corrector|
|
53
|
-
send_node = node.parent.parent
|
54
|
+
private
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
def autocorrect(corrector, send_node, node, option_nodes)
|
57
|
+
rel_node = nil
|
58
|
+
option_nodes.map(&:children).each do |options|
|
59
|
+
rel_node ||= options.find { |o| rel_node?(o) }
|
60
|
+
end
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
62
|
+
if rel_node
|
63
|
+
append_to_rel(rel_node, corrector)
|
64
|
+
else
|
65
|
+
add_rel(send_node, node, corrector)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
private
|
70
|
-
|
71
69
|
def append_to_rel(rel_node, corrector)
|
72
70
|
existing_rel = rel_node.children.last.value
|
73
71
|
str_range = rel_node.children.last.loc.expression.adjust(
|
@@ -89,7 +87,7 @@ module RuboCop
|
|
89
87
|
def contains_noopener?(value)
|
90
88
|
return false unless value
|
91
89
|
|
92
|
-
rel_array = value.to_s.split
|
90
|
+
rel_array = value.to_s.split
|
93
91
|
rel_array.include?('noopener') || rel_array.include?('noreferrer')
|
94
92
|
end
|
95
93
|
end
|
@@ -23,7 +23,9 @@ module RuboCop
|
|
23
23
|
# class UserMailer < ApplicationMailer
|
24
24
|
# end
|
25
25
|
#
|
26
|
-
class MailerName <
|
26
|
+
class MailerName < Base
|
27
|
+
extend AutoCorrector
|
28
|
+
|
27
29
|
MSG = 'Mailer should end with `Mailer` suffix.'
|
28
30
|
|
29
31
|
def_node_matcher :mailer_base_class?, <<~PATTERN
|
@@ -43,7 +45,9 @@ module RuboCop
|
|
43
45
|
|
44
46
|
def on_class(node)
|
45
47
|
class_definition?(node) do |name_node|
|
46
|
-
add_offense(name_node)
|
48
|
+
add_offense(name_node) do |corrector|
|
49
|
+
autocorrect(corrector, name_node)
|
50
|
+
end
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
@@ -54,23 +58,25 @@ module RuboCop
|
|
54
58
|
return unless casgn_parent
|
55
59
|
|
56
60
|
name = casgn_parent.children[1]
|
57
|
-
|
58
|
-
end
|
61
|
+
return if mailer_suffix?(name)
|
59
62
|
|
60
|
-
|
61
|
-
|
62
|
-
if node.casgn_type?
|
63
|
-
name = node.children[1]
|
64
|
-
corrector.replace(node.loc.name, "#{name}Mailer")
|
65
|
-
else
|
66
|
-
name = node.children.last
|
67
|
-
corrector.replace(node.source_range, "#{name}Mailer")
|
68
|
-
end
|
63
|
+
add_offense(casgn_parent.loc.name) do |corrector|
|
64
|
+
autocorrect(corrector, casgn_parent)
|
69
65
|
end
|
70
66
|
end
|
71
67
|
|
72
68
|
private
|
73
69
|
|
70
|
+
def autocorrect(corrector, node)
|
71
|
+
if node.casgn_type?
|
72
|
+
name = node.children[1]
|
73
|
+
corrector.replace(node.loc.name, "#{name}Mailer")
|
74
|
+
else
|
75
|
+
name = node.children.last
|
76
|
+
corrector.replace(node.source_range, "#{name}Mailer")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
74
80
|
def mailer_suffix?(mailer_name)
|
75
81
|
mailer_name.to_s.end_with?('Mailer')
|
76
82
|
end
|
@@ -20,8 +20,11 @@ module RuboCop
|
|
20
20
|
# match 'photos/:id', to: 'photos#show', via: [:get, :post]
|
21
21
|
# match 'photos/:id', to: 'photos#show', via: :all
|
22
22
|
#
|
23
|
-
class MatchRoute <
|
23
|
+
class MatchRoute < Base
|
24
|
+
extend AutoCorrector
|
25
|
+
|
24
26
|
MSG = 'Use `%<http_method>s` instead of `match` to define a route.'
|
27
|
+
RESTRICT_ON_SEND = %i[match].freeze
|
25
28
|
HTTP_METHODS = %i[get post put patch delete].freeze
|
26
29
|
|
27
30
|
def_node_matcher :match_method_call?, <<~PATTERN
|
@@ -35,30 +38,28 @@ module RuboCop
|
|
35
38
|
options_node = path_node.hash_type? ? path_node : options_node.first
|
36
39
|
|
37
40
|
if options_node.nil?
|
38
|
-
|
39
|
-
add_offense(node, message: message)
|
41
|
+
register_offense(node, 'get')
|
40
42
|
else
|
41
43
|
via = extract_via(options_node)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
44
|
+
return unless via.size == 1 && http_method?(via.first)
|
45
|
+
|
46
|
+
register_offense(node, via.first)
|
46
47
|
end
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
private
|
52
|
+
|
53
|
+
def register_offense(node, http_method)
|
54
|
+
add_offense(node, message: format(MSG, http_method: http_method)) do |corrector|
|
55
|
+
match_method_call?(node) do |path_node, options_node|
|
56
|
+
options_node = options_node.first
|
53
57
|
|
54
|
-
lambda do |corrector|
|
55
58
|
corrector.replace(node, replacement(path_node, options_node))
|
56
59
|
end
|
57
60
|
end
|
58
61
|
end
|
59
62
|
|
60
|
-
private
|
61
|
-
|
62
63
|
def_node_matcher :routes_draw?, <<~PATTERN
|
63
64
|
(send (send _ :routes) :draw)
|
64
65
|
PATTERN
|
@@ -77,6 +78,8 @@ module RuboCop
|
|
77
78
|
[via.value]
|
78
79
|
elsif via.array_type?
|
79
80
|
via.values.map(&:value)
|
81
|
+
else
|
82
|
+
[]
|
80
83
|
end
|
81
84
|
end
|
82
85
|
|
@@ -6,6 +6,9 @@ module RuboCop
|
|
6
6
|
# This cop enforces the use of `collection.exclude?(obj)`
|
7
7
|
# over `!collection.include?(obj)`.
|
8
8
|
#
|
9
|
+
# It is marked as unsafe by default because false positive will occur for
|
10
|
+
# a receiver object that do not have `exclude?` method. (e.g. `IPAddr`)
|
11
|
+
#
|
9
12
|
# @example
|
10
13
|
# # bad
|
11
14
|
# !array.include?(2)
|
@@ -15,22 +18,21 @@ module RuboCop
|
|
15
18
|
# array.exclude?(2)
|
16
19
|
# hash.exclude?(:key)
|
17
20
|
#
|
18
|
-
class NegateInclude <
|
21
|
+
class NegateInclude < Base
|
22
|
+
extend AutoCorrector
|
23
|
+
|
19
24
|
MSG = 'Use `.exclude?` and remove the negation part.'
|
25
|
+
RESTRICT_ON_SEND = %i[!].freeze
|
20
26
|
|
21
27
|
def_node_matcher :negate_include_call?, <<~PATTERN
|
22
28
|
(send (send $_ :include? $_) :!)
|
23
29
|
PATTERN
|
24
30
|
|
25
31
|
def on_send(node)
|
26
|
-
|
27
|
-
end
|
32
|
+
return unless (receiver, obj = negate_include_call?(node))
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
lambda do |corrector|
|
32
|
-
corrector.replace(node, "#{receiver.source}.exclude?(#{obj.source})")
|
33
|
-
end
|
34
|
+
add_offense(node) do |corrector|
|
35
|
+
corrector.replace(node, "#{receiver.source}.exclude?(#{obj.source})")
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
@@ -16,8 +16,9 @@ module RuboCop
|
|
16
16
|
# add_column :users, :name, :string, null: false, default: ''
|
17
17
|
# add_reference :products, :category
|
18
18
|
# add_reference :products, :category, null: false, default: 1
|
19
|
-
class NotNullColumn <
|
19
|
+
class NotNullColumn < Base
|
20
20
|
MSG = 'Do not add a NOT NULL column without a default value.'
|
21
|
+
RESTRICT_ON_SEND = %i[add_column add_reference].freeze
|
21
22
|
|
22
23
|
def_node_matcher :add_not_null_column?, <<~PATTERN
|
23
24
|
(send nil? :add_column _ _ _ (hash $...))
|