rubocop-rails 2.8.1 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) 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 +15 -3
  7. data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
  8. data/lib/rubocop/cop/mixin/index_method.rb +8 -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 +17 -12
  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/add_column_index.rb +64 -0
  15. data/lib/rubocop/cop/rails/after_commit_override.rb +1 -1
  16. data/lib/rubocop/cop/rails/application_controller.rb +3 -7
  17. data/lib/rubocop/cop/rails/application_job.rb +2 -1
  18. data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
  19. data/lib/rubocop/cop/rails/application_record.rb +2 -7
  20. data/lib/rubocop/cop/rails/arel_star.rb +41 -0
  21. data/lib/rubocop/cop/rails/assert_not.rb +8 -10
  22. data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
  23. data/lib/rubocop/cop/rails/belongs_to.rb +10 -19
  24. data/lib/rubocop/cop/rails/blank.rb +31 -27
  25. data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
  26. data/lib/rubocop/cop/rails/content_tag.rb +33 -18
  27. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
  28. data/lib/rubocop/cop/rails/date.rb +27 -17
  29. data/lib/rubocop/cop/rails/default_scope.rb +11 -4
  30. data/lib/rubocop/cop/rails/delegate.rb +9 -9
  31. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
  32. data/lib/rubocop/cop/rails/dynamic_find_by.rb +16 -13
  33. data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +78 -0
  34. data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
  35. data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
  36. data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
  37. data/lib/rubocop/cop/rails/environment_variable_access.rb +67 -0
  38. data/lib/rubocop/cop/rails/exit.rb +4 -10
  39. data/lib/rubocop/cop/rails/expanded_date_range.rb +86 -0
  40. data/lib/rubocop/cop/rails/file_path.rb +6 -7
  41. data/lib/rubocop/cop/rails/find_by.rb +32 -24
  42. data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
  43. data/lib/rubocop/cop/rails/find_each.rb +19 -18
  44. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
  45. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +37 -6
  46. data/lib/rubocop/cop/rails/helper_instance_variable.rb +29 -3
  47. data/lib/rubocop/cop/rails/http_positional_arguments.rb +26 -21
  48. data/lib/rubocop/cop/rails/http_status.rb +18 -11
  49. data/lib/rubocop/cop/rails/i18n_locale_assignment.rb +37 -0
  50. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
  51. data/lib/rubocop/cop/rails/index_by.rb +2 -1
  52. data/lib/rubocop/cop/rails/index_with.rb +2 -1
  53. data/lib/rubocop/cop/rails/inquiry.rb +4 -3
  54. data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
  55. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
  56. data/lib/rubocop/cop/rails/link_to_blank.rb +25 -23
  57. data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
  58. data/lib/rubocop/cop/rails/match_route.rb +14 -13
  59. data/lib/rubocop/cop/rails/negate_include.rb +10 -8
  60. data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
  61. data/lib/rubocop/cop/rails/order_by_id.rb +1 -2
  62. data/lib/rubocop/cop/rails/output.rb +5 -2
  63. data/lib/rubocop/cop/rails/output_safety.rb +3 -2
  64. data/lib/rubocop/cop/rails/pick.rb +14 -12
  65. data/lib/rubocop/cop/rails/pluck.rb +6 -9
  66. data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
  67. data/lib/rubocop/cop/rails/pluck_in_where.rb +7 -7
  68. data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
  69. data/lib/rubocop/cop/rails/presence.rb +12 -13
  70. data/lib/rubocop/cop/rails/present.rb +30 -24
  71. data/lib/rubocop/cop/rails/rake_environment.rb +8 -10
  72. data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
  73. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
  74. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
  75. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
  76. data/lib/rubocop/cop/rails/reflection_class_name.rb +17 -3
  77. data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
  78. data/lib/rubocop/cop/rails/relative_date_constant.rb +34 -27
  79. data/lib/rubocop/cop/rails/render_inline.rb +2 -1
  80. data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
  81. data/lib/rubocop/cop/rails/request_referer.rb +7 -7
  82. data/lib/rubocop/cop/rails/require_dependency.rb +38 -0
  83. data/lib/rubocop/cop/rails/reversible_migration.rb +3 -7
  84. data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
  85. data/lib/rubocop/cop/rails/safe_navigation.rb +30 -11
  86. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
  87. data/lib/rubocop/cop/rails/save_bang.rb +17 -20
  88. data/lib/rubocop/cop/rails/scope_args.rb +2 -1
  89. data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
  90. data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
  91. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +5 -6
  92. data/lib/rubocop/cop/rails/time_zone.rb +44 -42
  93. data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
  94. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +4 -6
  95. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +2 -2
  96. data/lib/rubocop/cop/rails/unknown_env.rb +3 -3
  97. data/lib/rubocop/cop/rails/unused_ignored_columns.rb +69 -0
  98. data/lib/rubocop/cop/rails/validation.rb +15 -14
  99. data/lib/rubocop/cop/rails/where_equals.rb +98 -0
  100. data/lib/rubocop/cop/rails/where_exists.rb +19 -13
  101. data/lib/rubocop/cop/rails/where_not.rb +10 -17
  102. data/lib/rubocop/cop/rails_cops.rb +13 -0
  103. data/lib/rubocop/rails.rb +2 -0
  104. data/lib/rubocop/rails/schema_loader.rb +4 -4
  105. data/lib/rubocop/rails/schema_loader/schema.rb +3 -5
  106. data/lib/rubocop/rails/version.rb +5 -1
  107. metadata +34 -14
@@ -4,6 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  # Common functionality for Rails/IndexBy and Rails/IndexWith
6
6
  module IndexMethod # rubocop:disable Metrics/ModuleLength
7
+ RESTRICT_ON_SEND = %i[each_with_object to_h map collect []].freeze
8
+
7
9
  def on_block(node)
8
10
  on_bad_each_with_object(node) do |*match|
9
11
  handle_possible_offense(node, match, 'each_with_object')
@@ -32,13 +34,6 @@ module RuboCop
32
34
  end
33
35
  end
34
36
 
35
- def autocorrect(node)
36
- lambda do |corrector|
37
- correction = prepare_correction(node)
38
- execute_correction(corrector, node, correction)
39
- end
40
- end
41
-
42
37
  private
43
38
 
44
39
  # @abstract Implemented with `def_node_matcher`
@@ -67,9 +62,11 @@ module RuboCop
67
62
  return if captures.noop_transformation?
68
63
 
69
64
  add_offense(
70
- node,
71
- message: "Prefer `#{new_method_name}` over `#{match_desc}`."
72
- )
65
+ node, message: "Prefer `#{new_method_name}` over `#{match_desc}`."
66
+ ) do |corrector|
67
+ correction = prepare_correction(node)
68
+ execute_correction(corrector, node, correction)
69
+ end
73
70
  end
74
71
 
75
72
  def extract_captures(match)
@@ -119,7 +116,7 @@ module RuboCop
119
116
  end
120
117
 
121
118
  # Internal helper class to hold autocorrect data
122
- Autocorrection = Struct.new(:match, :block_node, :leading, :trailing) do # rubocop:disable Metrics/BlockLength
119
+ Autocorrection = Struct.new(:match, :block_node, :leading, :trailing) do
123
120
  def self.from_each_with_object(node, match)
124
121
  new(match, node, 0, 0)
125
122
  end
@@ -29,8 +29,9 @@ module RuboCop
29
29
  # after_filter :do_stuff
30
30
  # append_around_filter :do_stuff
31
31
  # skip_after_filter :do_stuff
32
- class ActionFilter < Cop
32
+ class ActionFilter < Base
33
33
  include ConfigurableEnforcedStyle
34
+ extend AutoCorrector
34
35
 
35
36
  MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
36
37
 
@@ -66,6 +67,8 @@ module RuboCop
66
67
  skip_action_callback
67
68
  ].freeze
68
69
 
70
+ RESTRICT_ON_SEND = FILTER_METHODS + ACTION_METHODS
71
+
69
72
  def on_block(node)
70
73
  check_method_node(node.send_node)
71
74
  end
@@ -74,24 +77,17 @@ module RuboCop
74
77
  check_method_node(node) unless node.receiver
75
78
  end
76
79
 
77
- def autocorrect(node)
78
- lambda do |corrector|
79
- corrector.replace(node.loc.selector,
80
- preferred_method(node.loc.selector.source).to_s)
81
- end
82
- end
83
-
84
80
  private
85
81
 
86
82
  def check_method_node(node)
87
- return unless bad_methods.include?(node.method_name)
83
+ method_name = node.method_name
84
+ return unless bad_methods.include?(method_name)
88
85
 
89
- add_offense(node, location: :selector)
90
- end
86
+ message = format(MSG, prefer: preferred_method(method_name), current: method_name)
91
87
 
92
- def message(node)
93
- format(MSG, prefer: preferred_method(node.method_name),
94
- current: node.method_name)
88
+ add_offense(node.loc.selector, message: message) do |corrector|
89
+ corrector.replace(node.loc.selector, preferred_method(node.loc.selector.source))
90
+ end
95
91
  end
96
92
 
97
93
  def bad_methods
@@ -12,7 +12,9 @@ module RuboCop
12
12
  #
13
13
  # #good
14
14
  # Book.update!(author: 'Alice')
15
- class ActiveRecordAliases < Cop
15
+ class ActiveRecordAliases < Base
16
+ extend AutoCorrector
17
+
16
18
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
17
19
 
18
20
  ALIASES = {
@@ -20,28 +22,22 @@ module RuboCop
20
22
  update_attributes!: :update!
21
23
  }.freeze
22
24
 
25
+ RESTRICT_ON_SEND = ALIASES.keys.freeze
26
+
23
27
  def on_send(node)
24
- ALIASES.each do |bad, good|
25
- next unless node.method?(bad)
28
+ method_name = node.method_name
29
+ alias_method = ALIASES[method_name]
26
30
 
27
- add_offense(node,
28
- message: format(MSG, prefer: good, current: bad),
29
- location: :selector,
30
- severity: :warning)
31
- break
31
+ add_offense(
32
+ node.loc.selector,
33
+ message: format(MSG, prefer: alias_method, current: method_name),
34
+ severity: :warning
35
+ ) do |corrector|
36
+ corrector.replace(node.loc.selector, alias_method)
32
37
  end
33
38
  end
34
39
 
35
40
  alias on_csend on_send
36
-
37
- def autocorrect(node)
38
- lambda do |corrector|
39
- corrector.replace(
40
- node.loc.selector,
41
- ALIASES[node.method_name].to_s
42
- )
43
- end
44
- end
45
41
  end
46
42
  end
47
43
  end
@@ -19,7 +19,9 @@ module RuboCop
19
19
  # after_commit :after_commit_callback
20
20
  # end
21
21
  #
22
- class ActiveRecordCallbacksOrder < Cop
22
+ class ActiveRecordCallbacksOrder < Base
23
+ extend AutoCorrector
24
+
23
25
  MSG = '`%<current>s` is supposed to appear before `%<previous>s`.'
24
26
 
25
27
  CALLBACKS_IN_ORDER = %i[
@@ -55,17 +57,20 @@ module RuboCop
55
57
  index = CALLBACKS_ORDER_MAP[callback]
56
58
 
57
59
  if index < previous_index
58
- message = format(MSG, current: callback,
59
- previous: previous_callback)
60
- add_offense(node, message: message)
60
+ message = format(MSG, current: callback, previous: previous_callback)
61
+ add_offense(node, message: message) do |corrector|
62
+ autocorrect(corrector, node)
63
+ end
61
64
  end
62
65
  previous_index = index
63
66
  previous_callback = callback
64
67
  end
65
68
  end
66
69
 
70
+ private
71
+
67
72
  # Autocorrect by swapping between two nodes autocorrecting them
68
- def autocorrect(node)
73
+ def autocorrect(corrector, node)
69
74
  previous = left_siblings_of(node).reverse_each.find do |sibling|
70
75
  callback?(sibling)
71
76
  end
@@ -73,14 +78,10 @@ module RuboCop
73
78
  current_range = source_range_with_comment(node)
74
79
  previous_range = source_range_with_comment(previous)
75
80
 
76
- lambda do |corrector|
77
- corrector.insert_before(previous_range, current_range.source)
78
- corrector.remove(current_range)
79
- end
81
+ corrector.insert_before(previous_range, current_range.source)
82
+ corrector.remove(current_range)
80
83
  end
81
84
 
82
- private
83
-
84
85
  def defined_callbacks(class_node)
85
86
  class_def = class_node.body
86
87
 
@@ -121,7 +122,7 @@ module RuboCop
121
122
 
122
123
  processed_source.comments_before_line(annotation_line)
123
124
  .reverse_each do |comment|
124
- if comment.location.line == annotation_line
125
+ if comment.location.line == annotation_line && !inline_comment?(comment)
125
126
  first_comment = comment
126
127
  annotation_line -= 1
127
128
  end
@@ -130,6 +131,10 @@ module RuboCop
130
131
  start_line_position(first_comment || node)
131
132
  end
132
133
 
134
+ def inline_comment?(comment)
135
+ !comment_line?(comment.loc.expression.source_line)
136
+ end
137
+
133
138
  def start_line_position(node)
134
139
  buffer.line_range(node.loc.line).begin_pos - 1
135
140
  end
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # end
25
25
  # end
26
26
  #
27
- class ActiveRecordOverride < Cop
27
+ class ActiveRecordOverride < Base
28
28
  MSG =
29
29
  'Use %<prefer>s callbacks instead of overriding the Active Record ' \
30
30
  'method `%<bad>s`.'
@@ -19,8 +19,11 @@ module RuboCop
19
19
  # [1, 2, 'a'].append('b')
20
20
  # [1, 2, 'a'].prepend('b')
21
21
  #
22
- class ActiveSupportAliases < Cop
22
+ class ActiveSupportAliases < Base
23
+ extend AutoCorrector
24
+
23
25
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
26
+ RESTRICT_ON_SEND = %i[starts_with? ends_with? append prepend].freeze
24
27
 
25
28
  ALIASES = {
26
29
  starts_with?: {
@@ -39,29 +42,17 @@ module RuboCop
39
42
 
40
43
  def on_send(node)
41
44
  ALIASES.each_key do |aliased_method|
42
- register_offense(node, aliased_method) if
43
- public_send(aliased_method, node)
44
- end
45
- end
45
+ next unless public_send(aliased_method, node)
46
46
 
47
- def autocorrect(node)
48
- return false if append(node)
47
+ preferred_method = ALIASES[aliased_method][:original]
48
+ message = format(MSG, prefer: preferred_method, current: aliased_method)
49
49
 
50
- lambda do |corrector|
51
- method_name = node.loc.selector.source
52
- replacement = ALIASES[method_name.to_sym][:original]
53
- corrector.replace(node.loc.selector, replacement.to_s)
54
- end
55
- end
56
-
57
- private
50
+ add_offense(node, message: message) do |corrector|
51
+ next if append(node)
58
52
 
59
- def register_offense(node, method_name)
60
- add_offense(
61
- node,
62
- message: format(MSG, prefer: ALIASES[method_name][:original],
63
- current: method_name)
64
- )
53
+ corrector.replace(node.loc.selector, preferred_method)
54
+ end
55
+ end
65
56
  end
66
57
  end
67
58
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks for migrations using `add_column` that have an `index`
7
+ # key. `add_column` does not accept `index`, but also does not raise an
8
+ # error for extra keys, so it is possible to mistakenly add the key without
9
+ # realizing it will not actually add an index.
10
+ #
11
+ # @example
12
+ # # bad (will not add an index)
13
+ # add_column :table, :column, :integer, index: true
14
+ #
15
+ # # good
16
+ # add_column :table, :column, :integer
17
+ # add_index :table, :column
18
+ #
19
+ class AddColumnIndex < Base
20
+ extend AutoCorrector
21
+ include RangeHelp
22
+
23
+ MSG = '`add_column` does not accept an `index` key, use `add_index` instead.'
24
+ RESTRICT_ON_SEND = %i[add_column].freeze
25
+
26
+ # @!method add_column_with_index(node)
27
+ def_node_matcher :add_column_with_index, <<~PATTERN
28
+ (
29
+ send nil? :add_column $_table $_column
30
+ <(hash <$(pair {(sym :index) (str "index")} $_) ...>) ...>
31
+ )
32
+ PATTERN
33
+
34
+ def on_send(node)
35
+ table, column, pair, value = add_column_with_index(node)
36
+ return unless pair
37
+
38
+ add_offense(pair) do |corrector|
39
+ corrector.remove(index_range(pair))
40
+
41
+ add_index = "add_index #{table.source}, #{column.source}"
42
+ add_index_opts = ''
43
+
44
+ if value.hash_type?
45
+ hash = value.loc.expression.adjust(begin_pos: 1, end_pos: -1).source.strip
46
+ add_index_opts = ", #{hash}"
47
+ end
48
+
49
+ corrector.insert_after(node, "\n#{add_index}#{add_index_opts}")
50
+ end
51
+ end
52
+
53
+ private
54
+
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
+ )
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -31,7 +31,7 @@ module RuboCop
31
31
  # after_create_commit :log_create_action
32
32
  # after_update_commit :log_update_action
33
33
  #
34
- class AfterCommitOverride < Cop
34
+ class AfterCommitOverride < Base
35
35
  MSG = 'There can only be one `after_*_commit :%<name>s` hook defined for a model.'
36
36
 
37
37
  AFTER_COMMIT_CALLBACKS = %i[
@@ -16,7 +16,9 @@ module RuboCop
16
16
  # class MyController < ActionController::Base
17
17
  # # ...
18
18
  # end
19
- class ApplicationController < Cop
19
+ class ApplicationController < Base
20
+ extend AutoCorrector
21
+
20
22
  MSG = 'Controllers should subclass `ApplicationController`.'
21
23
  SUPERCLASS = 'ApplicationController'
22
24
  BASE_PATTERN = '(const (const nil? :ActionController) :Base)'
@@ -24,12 +26,6 @@ module RuboCop
24
26
  # rubocop:disable Layout/ClassStructure
25
27
  include RuboCop::Cop::EnforceSuperclass
26
28
  # rubocop:enable Layout/ClassStructure
27
-
28
- def autocorrect(node)
29
- lambda do |corrector|
30
- corrector.replace(node.source_range, self.class::SUPERCLASS)
31
- end
32
- end
33
29
  end
34
30
  end
35
31
  end
@@ -16,7 +16,8 @@ module RuboCop
16
16
  # class Rails4Job < ActiveJob::Base
17
17
  # # ...
18
18
  # end
19
- class ApplicationJob < Cop
19
+ class ApplicationJob < Base
20
+ extend AutoCorrector
20
21
  extend TargetRailsVersion
21
22
 
22
23
  minimum_target_rails_version 5.0
@@ -16,7 +16,8 @@ module RuboCop
16
16
  # class MyMailer < ActionMailer::Base
17
17
  # # ...
18
18
  # end
19
- class ApplicationMailer < Cop
19
+ class ApplicationMailer < Base
20
+ extend AutoCorrector
20
21
  extend TargetRailsVersion
21
22
 
22
23
  minimum_target_rails_version 5.0
@@ -28,12 +29,6 @@ module RuboCop
28
29
  # rubocop:disable Layout/ClassStructure
29
30
  include RuboCop::Cop::EnforceSuperclass
30
31
  # rubocop:enable Layout/ClassStructure
31
-
32
- def autocorrect(node)
33
- lambda do |corrector|
34
- corrector.replace(node.source_range, self.class::SUPERCLASS)
35
- end
36
- end
37
32
  end
38
33
  end
39
34
  end
@@ -16,7 +16,8 @@ module RuboCop
16
16
  # class Rails4Model < ActiveRecord::Base
17
17
  # # ...
18
18
  # end
19
- class ApplicationRecord < Cop
19
+ class ApplicationRecord < Base
20
+ extend AutoCorrector
20
21
  extend TargetRailsVersion
21
22
 
22
23
  minimum_target_rails_version 5.0
@@ -28,12 +29,6 @@ module RuboCop
28
29
  # rubocop:disable Layout/ClassStructure
29
30
  include RuboCop::Cop::EnforceSuperclass
30
31
  # rubocop:enable Layout/ClassStructure
31
-
32
- def autocorrect(node)
33
- lambda do |corrector|
34
- corrector.replace(node.source_range, self.class::SUPERCLASS)
35
- end
36
- end
37
32
  end
38
33
  end
39
34
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop prevents usage of `"*"` on an Arel::Table column reference.
7
+ #
8
+ # Using `arel_table["*"]` causes the outputted string to be a literal
9
+ # quoted asterisk (e.g. <tt>`my_model`.`*`</tt>). This causes the
10
+ # database to look for a column named <tt>`*`</tt> (or `"*"`) as opposed
11
+ # to expanding the column list as one would likely expect.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # MyTable.arel_table["*"]
16
+ #
17
+ # # good
18
+ # MyTable.arel_table[Arel.star]
19
+ #
20
+ class ArelStar < Base
21
+ extend AutoCorrector
22
+
23
+ MSG = 'Use `Arel.star` instead of `"*"` for expanded column lists.'
24
+
25
+ RESTRICT_ON_SEND = %i[[]].freeze
26
+
27
+ def_node_matcher :star_bracket?, <<~PATTERN
28
+ (send {const (send _ :arel_table)} :[] $(str "*"))
29
+ PATTERN
30
+
31
+ def on_send(node)
32
+ return unless (star = star_bracket?(node))
33
+
34
+ add_offense(star) do |corrector|
35
+ corrector.replace(star.loc.expression, 'Arel.star')
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end