rubocop-rails 2.7.1 → 2.10.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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +18 -2
  4. data/config/default.yml +144 -6
  5. data/config/obsoletion.yml +7 -0
  6. data/lib/rubocop/cop/mixin/active_record_helper.rb +16 -3
  7. data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
  8. data/lib/rubocop/cop/mixin/index_method.rb +25 -11
  9. data/lib/rubocop/cop/rails/action_filter.rb +10 -14
  10. data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
  11. data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +19 -16
  12. data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
  13. data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
  14. data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
  15. data/lib/rubocop/cop/rails/application_controller.rb +3 -7
  16. data/lib/rubocop/cop/rails/application_job.rb +2 -1
  17. data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
  18. data/lib/rubocop/cop/rails/application_record.rb +2 -7
  19. data/lib/rubocop/cop/rails/arel_star.rb +41 -0
  20. data/lib/rubocop/cop/rails/assert_not.rb +8 -10
  21. data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
  22. data/lib/rubocop/cop/rails/belongs_to.rb +10 -19
  23. data/lib/rubocop/cop/rails/blank.rb +31 -27
  24. data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
  25. data/lib/rubocop/cop/rails/content_tag.rb +34 -19
  26. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
  27. data/lib/rubocop/cop/rails/date.rb +10 -11
  28. data/lib/rubocop/cop/rails/default_scope.rb +11 -4
  29. data/lib/rubocop/cop/rails/delegate.rb +9 -9
  30. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
  31. data/lib/rubocop/cop/rails/dynamic_find_by.rb +15 -12
  32. data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
  33. data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
  34. data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
  35. data/lib/rubocop/cop/rails/environment_variable_access.rb +67 -0
  36. data/lib/rubocop/cop/rails/exit.rb +4 -10
  37. data/lib/rubocop/cop/rails/file_path.rb +7 -8
  38. data/lib/rubocop/cop/rails/find_by.rb +13 -13
  39. data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
  40. data/lib/rubocop/cop/rails/find_each.rb +19 -18
  41. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
  42. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +37 -10
  43. data/lib/rubocop/cop/rails/helper_instance_variable.rb +30 -2
  44. data/lib/rubocop/cop/rails/http_positional_arguments.rb +32 -21
  45. data/lib/rubocop/cop/rails/http_status.rb +7 -9
  46. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
  47. data/lib/rubocop/cop/rails/index_by.rb +11 -2
  48. data/lib/rubocop/cop/rails/index_with.rb +11 -2
  49. data/lib/rubocop/cop/rails/inquiry.rb +7 -2
  50. data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
  51. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
  52. data/lib/rubocop/cop/rails/link_to_blank.rb +25 -23
  53. data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
  54. data/lib/rubocop/cop/rails/match_route.rb +14 -13
  55. data/lib/rubocop/cop/rails/negate_include.rb +10 -8
  56. data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
  57. data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
  58. data/lib/rubocop/cop/rails/output.rb +5 -2
  59. data/lib/rubocop/cop/rails/output_safety.rb +3 -2
  60. data/lib/rubocop/cop/rails/pick.rb +14 -12
  61. data/lib/rubocop/cop/rails/pluck.rb +6 -9
  62. data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
  63. data/lib/rubocop/cop/rails/pluck_in_where.rb +39 -5
  64. data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
  65. data/lib/rubocop/cop/rails/presence.rb +12 -13
  66. data/lib/rubocop/cop/rails/present.rb +30 -24
  67. data/lib/rubocop/cop/rails/rake_environment.rb +8 -10
  68. data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
  69. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
  70. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
  71. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
  72. data/lib/rubocop/cop/rails/reflection_class_name.rb +18 -4
  73. data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
  74. data/lib/rubocop/cop/rails/relative_date_constant.rb +34 -22
  75. data/lib/rubocop/cop/rails/render_inline.rb +2 -1
  76. data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
  77. data/lib/rubocop/cop/rails/request_referer.rb +7 -7
  78. data/lib/rubocop/cop/rails/require_dependency.rb +38 -0
  79. data/lib/rubocop/cop/rails/reversible_migration.rb +83 -8
  80. data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
  81. data/lib/rubocop/cop/rails/safe_navigation.rb +30 -11
  82. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
  83. data/lib/rubocop/cop/rails/save_bang.rb +19 -22
  84. data/lib/rubocop/cop/rails/scope_args.rb +2 -1
  85. data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
  86. data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
  87. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
  88. data/lib/rubocop/cop/rails/time_zone.rb +35 -25
  89. data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
  90. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +6 -6
  91. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
  92. data/lib/rubocop/cop/rails/unknown_env.rb +3 -3
  93. data/lib/rubocop/cop/rails/validation.rb +15 -14
  94. data/lib/rubocop/cop/rails/where_equals.rb +98 -0
  95. data/lib/rubocop/cop/rails/where_exists.rb +85 -16
  96. data/lib/rubocop/cop/rails/where_not.rb +101 -0
  97. data/lib/rubocop/cop/rails_cops.rb +12 -0
  98. data/lib/rubocop/rails.rb +2 -0
  99. data/lib/rubocop/rails/schema_loader.rb +4 -4
  100. data/lib/rubocop/rails/schema_loader/schema.rb +4 -8
  101. data/lib/rubocop/rails/version.rb +5 -1
  102. metadata +33 -14
@@ -23,8 +23,11 @@ module RuboCop
23
23
  # # good
24
24
  # x = self[:attr]
25
25
  # self[:attr] = val
26
- class ReadWriteAttribute < Cop
26
+ class ReadWriteAttribute < Base
27
+ extend AutoCorrector
28
+
27
29
  MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
30
+ RESTRICT_ON_SEND = %i[read_attribute write_attribute].freeze
28
31
 
29
32
  def_node_matcher :read_write_attribute?, <<~PATTERN
30
33
  {
@@ -36,18 +39,16 @@ module RuboCop
36
39
  def on_send(node)
37
40
  return unless read_write_attribute?(node)
38
41
 
39
- add_offense(node, location: :selector)
40
- end
42
+ add_offense(node.loc.selector, message: message(node)) do |corrector|
43
+ case node.method_name
44
+ when :read_attribute
45
+ replacement = read_attribute_replacement(node)
46
+ when :write_attribute
47
+ replacement = write_attribute_replacement(node)
48
+ end
41
49
 
42
- def autocorrect(node)
43
- case node.method_name
44
- when :read_attribute
45
- replacement = read_attribute_replacement(node)
46
- when :write_attribute
47
- replacement = write_attribute_replacement(node)
50
+ corrector.replace(node.source_range, replacement)
48
51
  end
49
-
50
- ->(corrector) { corrector.replace(node.source_range, replacement) }
51
52
  end
52
53
 
53
54
  private
@@ -26,8 +26,9 @@ module RuboCop
26
26
  # # Here, `nil` is valid but `''` is not
27
27
  # validates :x, length: { is: 5 }, allow_nil: true, allow_blank: false
28
28
  #
29
- class RedundantAllowNil < Cop
29
+ class RedundantAllowNil < Base
30
30
  include RangeHelp
31
+ extend AutoCorrector
31
32
 
32
33
  MSG_SAME =
33
34
  '`allow_nil` is redundant when `allow_blank` has the same value.'
@@ -35,59 +36,56 @@ module RuboCop
35
36
  MSG_ALLOW_NIL_FALSE =
36
37
  '`allow_nil: false` is redundant when `allow_blank` is true.'
37
38
 
38
- def on_send(node)
39
- return unless node.method?(:validates)
39
+ RESTRICT_ON_SEND = %i[validates].freeze
40
40
 
41
+ def on_send(node)
41
42
  allow_nil, allow_blank = find_allow_nil_and_allow_blank(node)
42
43
  return unless allow_nil && allow_blank
43
44
 
44
45
  allow_nil_val = allow_nil.children.last
45
46
  allow_blank_val = allow_blank.children.last
46
47
 
47
- offense(allow_nil_val, allow_blank_val, allow_nil)
48
+ if allow_nil_val.type == allow_blank_val.type
49
+ register_offense(allow_nil, MSG_SAME)
50
+ elsif allow_nil_val.false_type? && allow_blank_val.true_type?
51
+ register_offense(allow_nil, MSG_ALLOW_NIL_FALSE)
52
+ end
48
53
  end
49
54
 
50
- def autocorrect(node)
51
- prv_sib = previous_sibling(node)
52
- nxt_sib = next_sibling(node)
55
+ private
56
+
57
+ def register_offense(allow_nil, message)
58
+ add_offense(allow_nil, message: message) do |corrector|
59
+ prv_sib = previous_sibling(allow_nil)
60
+ nxt_sib = next_sibling(allow_nil)
53
61
 
54
- lambda do |corrector|
55
62
  if nxt_sib
56
- corrector.remove(range_between(node_beg(node), node_beg(nxt_sib)))
63
+ corrector.remove(range_between(node_beg(allow_nil), node_beg(nxt_sib)))
57
64
  elsif prv_sib
58
- corrector.remove(range_between(node_end(prv_sib), node_end(node)))
65
+ corrector.remove(range_between(node_end(prv_sib), node_end(allow_nil)))
59
66
  else
60
- corrector.remove(node.loc.expression)
67
+ corrector.remove(allow_nil.loc.expression)
61
68
  end
62
69
  end
63
70
  end
64
71
 
65
- private
66
-
67
- def offense(allow_nil_val, allow_blank_val, allow_nil)
68
- if allow_nil_val.type == allow_blank_val.type
69
- add_offense(allow_nil, message: MSG_SAME)
70
- elsif allow_nil_val.false_type? && allow_blank_val.true_type?
71
- add_offense(allow_nil, message: MSG_ALLOW_NIL_FALSE)
72
- end
73
- end
74
-
75
72
  def find_allow_nil_and_allow_blank(node)
76
- allow_nil = nil
77
- allow_blank = nil
73
+ allow_nil, allow_blank = nil
78
74
 
79
- node.each_descendant do |descendant|
80
- next unless descendant.pair_type?
75
+ node.each_child_node do |child_node|
76
+ if child_node.pair_type?
77
+ key = child_node.children.first.source
81
78
 
82
- key = descendant.children.first.source
83
-
84
- allow_nil = descendant if key == 'allow_nil'
85
- allow_blank = descendant if key == 'allow_blank'
79
+ allow_nil = child_node if key == 'allow_nil'
80
+ allow_blank = child_node if key == 'allow_blank'
81
+ end
82
+ return [allow_nil, allow_blank] if allow_nil && allow_blank
86
83
 
87
- break if allow_nil && allow_blank
84
+ found_in_children_nodes = find_allow_nil_and_allow_blank(child_node)
85
+ return found_in_children_nodes if found_in_children_nodes
88
86
  end
89
87
 
90
- [allow_nil, allow_blank]
88
+ nil
91
89
  end
92
90
 
93
91
  def previous_sibling(node)
@@ -24,10 +24,12 @@ module RuboCop
24
24
  # class Comment
25
25
  # belongs_to :author, foreign_key: 'user_id'
26
26
  # end
27
- class RedundantForeignKey < Cop
27
+ class RedundantForeignKey < Base
28
28
  include RangeHelp
29
+ extend AutoCorrector
29
30
 
30
31
  MSG = 'Specifying the default value for `foreign_key` is redundant.'
32
+ RESTRICT_ON_SEND = %i[belongs_to has_one has_many has_and_belongs_to_many].freeze
31
33
 
32
34
  def_node_matcher :association_with_foreign_key, <<~PATTERN
33
35
  (send nil? ${:belongs_to :has_one :has_many :has_and_belongs_to_many} ({sym str} $_)
@@ -38,18 +40,13 @@ module RuboCop
38
40
  def on_send(node)
39
41
  association_with_foreign_key(node) do |type, name, options, foreign_key_pair, foreign_key|
40
42
  if redundant?(node, type, name, options, foreign_key)
41
- add_offense(node, location: foreign_key_pair.loc.expression)
42
- end
43
- end
44
- end
43
+ add_offense(foreign_key_pair.loc.expression) do |corrector|
44
+ range = range_with_surrounding_space(range: foreign_key_pair.source_range, side: :left)
45
+ range = range_with_surrounding_comma(range, :left)
45
46
 
46
- def autocorrect(node)
47
- _type, _name, _options, foreign_key_pair, _foreign_key = association_with_foreign_key(node)
48
- range = range_with_surrounding_space(range: foreign_key_pair.source_range, side: :left)
49
- range = range_with_surrounding_comma(range, :left)
50
-
51
- lambda do |corrector|
52
- corrector.remove(range)
47
+ corrector.remove(range)
48
+ end
49
+ end
53
50
  end
54
51
  end
55
52
 
@@ -54,8 +54,9 @@ module RuboCop
54
54
  # merger.invoke(another_receiver)
55
55
  # end
56
56
  # end
57
- class RedundantReceiverInWithOptions < Cop
57
+ class RedundantReceiverInWithOptions < Base
58
58
  include RangeHelp
59
+ extend AutoCorrector
59
60
 
60
61
  MSG = 'Redundant receiver in `with_options`.'
61
62
 
@@ -86,22 +87,22 @@ module RuboCop
86
87
  if send_nodes.all? { |n| same_value?(arg, n.receiver) }
87
88
  send_nodes.each do |send_node|
88
89
  receiver = send_node.receiver
89
- add_offense(send_node, location: receiver.source_range)
90
+ add_offense(receiver.source_range) do |corrector|
91
+ autocorrect(corrector, send_node)
92
+ end
90
93
  end
91
94
  end
92
95
  end
93
96
  end
94
97
 
95
- def autocorrect(node)
96
- lambda do |corrector|
97
- corrector.remove(node.receiver.source_range)
98
- corrector.remove(node.loc.dot)
99
- corrector.remove(block_argument_range(node))
100
- end
101
- end
102
-
103
98
  private
104
99
 
100
+ def autocorrect(corrector, node)
101
+ corrector.remove(node.receiver.source_range)
102
+ corrector.remove(node.loc.dot)
103
+ corrector.remove(block_argument_range(node))
104
+ end
105
+
105
106
  def block_argument_range(node)
106
107
  block_node = node.each_ancestor(:block).first
107
108
  block_argument = block_node.children[1].source_range
@@ -5,6 +5,8 @@ module RuboCop
5
5
  module Rails
6
6
  # This cop checks if the value of the option `class_name`, in
7
7
  # the definition of a reflection is a string.
8
+ # It is marked as unsafe because it cannot be determined whether
9
+ # constant or method return value specified to `class_name` is a string.
8
10
  #
9
11
  # @example
10
12
  # # bad
@@ -13,22 +15,34 @@ module RuboCop
13
15
  #
14
16
  # # good
15
17
  # has_many :accounts, class_name: 'Account'
16
- class ReflectionClassName < Cop
18
+ class ReflectionClassName < Base
17
19
  MSG = 'Use a string value for `class_name`.'
20
+ RESTRICT_ON_SEND = %i[has_many has_one belongs_to].freeze
21
+ ALLOWED_REFLECTION_CLASS_TYPES = %i[dstr str sym].freeze
18
22
 
19
23
  def_node_matcher :association_with_reflection, <<~PATTERN
20
- (send nil? {:has_many :has_one :belongs_to} _
24
+ (send nil? {:has_many :has_one :belongs_to} _ _ ?
21
25
  (hash <$#reflection_class_name ...>)
22
26
  )
23
27
  PATTERN
24
28
 
25
29
  def_node_matcher :reflection_class_name, <<~PATTERN
26
- (pair (sym :class_name) [!dstr !str !sym])
30
+ (pair (sym :class_name) #reflection_class_value?)
27
31
  PATTERN
28
32
 
29
33
  def on_send(node)
30
34
  association_with_reflection(node) do |reflection_class_name|
31
- add_offense(node, location: reflection_class_name.loc.expression)
35
+ add_offense(reflection_class_name.loc.expression)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def reflection_class_value?(class_value)
42
+ if class_value.send_type?
43
+ !class_value.method?(:to_s) || class_value.receiver.const_type?
44
+ else
45
+ !ALLOWED_REFLECTION_CLASS_TYPES.include?(class_value.type)
32
46
  end
33
47
  end
34
48
  end
@@ -28,8 +28,9 @@ module RuboCop
28
28
  # refute_empty [1, 2, 3]
29
29
  # refute_equal true, false
30
30
  #
31
- class RefuteMethods < Cop
31
+ class RefuteMethods < Base
32
32
  include ConfigurableEnforcedStyle
33
+ extend AutoCorrector
33
34
 
34
35
  MSG = 'Prefer `%<good_method>s` over `%<bad_method>s`.'
35
36
 
@@ -53,21 +54,19 @@ module RuboCop
53
54
  REFUTE_METHODS = CORRECTIONS.keys.freeze
54
55
  ASSERT_NOT_METHODS = CORRECTIONS.values.freeze
55
56
 
57
+ RESTRICT_ON_SEND = REFUTE_METHODS + ASSERT_NOT_METHODS
58
+
56
59
  def_node_matcher :offensive?, '(send nil? #bad_method? ...)'
57
60
 
58
61
  def on_send(node)
59
62
  return unless offensive?(node)
60
63
 
61
- message = offense_message(node.method_name)
62
- add_offense(node, location: :selector, message: message)
63
- end
64
-
65
- def autocorrect(node)
66
- bad_method = node.method_name
67
- good_method = convert_good_method(bad_method)
64
+ method_name = node.method_name
65
+ message = offense_message(method_name)
66
+ range = node.loc.selector
68
67
 
69
- lambda do |corrector|
70
- corrector.replace(node.loc.selector, good_method.to_s)
68
+ add_offense(range, message: message) do |corrector|
69
+ corrector.replace(range, convert_good_method(method_name))
71
70
  end
72
71
  end
73
72
 
@@ -27,15 +27,23 @@ module RuboCop
27
27
  # 1.week.since
28
28
  # end
29
29
  # end
30
- class RelativeDateConstant < Cop
30
+ class RelativeDateConstant < Base
31
31
  include RangeHelp
32
+ extend AutoCorrector
32
33
 
33
- MSG = 'Do not assign %<method_name>s to constants as it ' \
34
+ MSG = 'Do not assign `%<method_name>s` to constants as it ' \
34
35
  'will be evaluated only once.'
36
+ RELATIVE_DATE_METHODS = %i[since from_now after ago until before yesterday tomorrow].freeze
35
37
 
36
38
  def on_casgn(node)
37
- relative_date_assignment?(node) do |method_name|
38
- add_offense(node, message: format(MSG, method_name: method_name))
39
+ return if node.children[2]&.block_type?
40
+
41
+ node.each_descendant(:send) do |send_node|
42
+ relative_date?(send_node) do |method_name|
43
+ add_offense(node, message: message(method_name)) do |corrector|
44
+ autocorrect(corrector, node)
45
+ end
46
+ end
39
47
  end
40
48
  end
41
49
 
@@ -48,10 +56,9 @@ module RuboCop
48
56
  next unless name.casgn_type?
49
57
 
50
58
  relative_date?(value) do |method_name|
51
- add_offense(node,
52
- location: range_between(name.loc.expression.begin_pos,
53
- value.loc.expression.end_pos),
54
- message: format(MSG, method_name: method_name))
59
+ add_offense(offense_range(name, value), message: message(method_name)) do |corrector|
60
+ autocorrect(corrector, node)
61
+ end
55
62
  end
56
63
  end
57
64
  end
@@ -62,7 +69,9 @@ module RuboCop
62
69
  end
63
70
  end
64
71
 
65
- def autocorrect(node)
72
+ private
73
+
74
+ def autocorrect(corrector, node)
66
75
  return unless node.casgn_type?
67
76
 
68
77
  scope, const_name, value = *node
@@ -72,28 +81,31 @@ module RuboCop
72
81
  new_code = ["def self.#{const_name.downcase}",
73
82
  "#{indent}#{value.source}",
74
83
  'end'].join("\n#{indent}")
75
- ->(corrector) { corrector.replace(node.source_range, new_code) }
84
+
85
+ corrector.replace(node.source_range, new_code)
76
86
  end
77
87
 
78
- private
88
+ def message(method_name)
89
+ format(MSG, method_name: method_name)
90
+ end
79
91
 
80
- def_node_matcher :relative_date_assignment?, <<~PATTERN
81
- {
82
- (casgn _ _ (send _ ${:since :from_now :after :ago :until :before}))
83
- (casgn _ _ ({erange irange} _ (send _ ${:since :from_now :after :ago :until :before})))
84
- (casgn _ _ ({erange irange} (send _ ${:since :from_now :after :ago :until :before}) _))
85
- }
86
- PATTERN
92
+ def offense_range(name, value)
93
+ range_between(name.loc.expression.begin_pos, value.loc.expression.end_pos)
94
+ end
95
+
96
+ def relative_date_method?(method_name)
97
+ RELATIVE_DATE_METHODS.include?(method_name)
98
+ end
87
99
 
88
100
  def_node_matcher :relative_date_or_assignment?, <<~PATTERN
89
- (:or_asgn (casgn _ _) (send _ ${:since :from_now :after :ago :until :before}))
101
+ (:or_asgn (casgn _ _) (send _ $#relative_date_method?))
90
102
  PATTERN
91
103
 
92
104
  def_node_matcher :relative_date?, <<~PATTERN
93
105
  {
94
- ({erange irange} _ (send _ ${:since :from_now :after :ago :until :before}))
95
- ({erange irange} (send _ ${:since :from_now :after :ago :until :before}) _)
96
- (send _ ${:since :from_now :after :ago :until :before})
106
+ ({erange irange} _ (send _ $#relative_date_method?))
107
+ ({erange irange} (send _ $#relative_date_method?) _)
108
+ (send _ $#relative_date_method?)
97
109
  }
98
110
  PATTERN
99
111
  end
@@ -24,8 +24,9 @@ module RuboCop
24
24
  # end
25
25
  # end
26
26
  #
27
- class RenderInline < Cop
27
+ class RenderInline < Base
28
28
  MSG = 'Prefer using a template over inline rendering.'
29
+ RESTRICT_ON_SEND = %i[render].freeze
29
30
 
30
31
  def_node_matcher :render_with_inline_option?, <<~PATTERN
31
32
  (send nil? :render (hash <(pair {(sym :inline) (str "inline")} _) ...>))
@@ -24,30 +24,25 @@ module RuboCop
24
24
  # # bad - sets MIME type to `text/html`
25
25
  # render text: 'Ruby!'
26
26
  #
27
- class RenderPlainText < Cop
27
+ class RenderPlainText < Base
28
+ extend AutoCorrector
29
+
28
30
  MSG = 'Prefer `render plain:` over `render text:`.'
31
+ RESTRICT_ON_SEND = %i[render].freeze
29
32
 
30
33
  def_node_matcher :render_plain_text?, <<~PATTERN
31
34
  (send nil? :render $(hash <$(pair (sym :text) $_) ...>))
32
35
  PATTERN
33
36
 
34
37
  def on_send(node)
35
- render_plain_text?(node) do |options_node, _option_node, _option_value|
36
- content_type_node = find_content_type(options_node)
37
- add_offense(node) if compatible_content_type?(content_type_node)
38
- end
39
- end
40
-
41
- def autocorrect(node)
42
38
  render_plain_text?(node) do |options_node, option_node, option_value|
43
39
  content_type_node = find_content_type(options_node)
44
- rest_options = options_node.pairs - [option_node, content_type_node].compact
40
+ return unless compatible_content_type?(content_type_node)
41
+
42
+ add_offense(node) do |corrector|
43
+ rest_options = options_node.pairs - [option_node, content_type_node].compact
45
44
 
46
- lambda do |corrector|
47
- corrector.replace(
48
- node,
49
- replacement(rest_options, option_value)
50
- )
45
+ corrector.replace(node, replacement(rest_options, option_value))
51
46
  end
52
47
  end
53
48
  end