rubocop-rails 2.14.2 → 2.19.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -2
  4. data/config/default.yml +190 -12
  5. data/config/obsoletion.yml +10 -0
  6. data/lib/rubocop/cop/mixin/active_record_helper.rb +3 -6
  7. data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +1 -3
  8. data/lib/rubocop/cop/mixin/enforce_superclass.rb +1 -1
  9. data/lib/rubocop/cop/mixin/index_method.rb +7 -17
  10. data/lib/rubocop/cop/mixin/migrations_helper.rb +1 -1
  11. data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +112 -0
  12. data/lib/rubocop/cop/rails/action_controller_test_case.rb +2 -2
  13. data/lib/rubocop/cop/rails/action_filter.rb +2 -2
  14. data/lib/rubocop/cop/rails/action_order.rb +116 -0
  15. data/lib/rubocop/cop/rails/active_record_aliases.rb +3 -4
  16. data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +7 -4
  17. data/lib/rubocop/cop/rails/active_record_override.rb +2 -5
  18. data/lib/rubocop/cop/rails/active_support_aliases.rb +1 -1
  19. data/lib/rubocop/cop/rails/active_support_on_load.rb +70 -0
  20. data/lib/rubocop/cop/rails/add_column_index.rb +3 -6
  21. data/lib/rubocop/cop/rails/after_commit_override.rb +1 -1
  22. data/lib/rubocop/cop/rails/application_controller.rb +2 -2
  23. data/lib/rubocop/cop/rails/application_job.rb +3 -3
  24. data/lib/rubocop/cop/rails/application_mailer.rb +2 -2
  25. data/lib/rubocop/cop/rails/application_record.rb +2 -2
  26. data/lib/rubocop/cop/rails/arel_star.rb +2 -2
  27. data/lib/rubocop/cop/rails/assert_not.rb +1 -1
  28. data/lib/rubocop/cop/rails/attribute_default_block_value.rb +1 -1
  29. data/lib/rubocop/cop/rails/belongs_to.rb +2 -5
  30. data/lib/rubocop/cop/rails/blank.rb +10 -11
  31. data/lib/rubocop/cop/rails/bulk_change_table.rb +8 -25
  32. data/lib/rubocop/cop/rails/compact_blank.rb +6 -2
  33. data/lib/rubocop/cop/rails/content_tag.rb +6 -7
  34. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +16 -3
  35. data/lib/rubocop/cop/rails/date.rb +12 -17
  36. data/lib/rubocop/cop/rails/default_scope.rb +1 -1
  37. data/lib/rubocop/cop/rails/delegate.rb +24 -18
  38. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +2 -2
  39. data/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +63 -3
  40. data/lib/rubocop/cop/rails/dot_separated_keys.rb +71 -0
  41. data/lib/rubocop/cop/rails/duplicate_association.rb +2 -2
  42. data/lib/rubocop/cop/rails/duplicate_scope.rb +1 -1
  43. data/lib/rubocop/cop/rails/duration_arithmetic.rb +4 -4
  44. data/lib/rubocop/cop/rails/dynamic_find_by.rb +26 -14
  45. data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +6 -2
  46. data/lib/rubocop/cop/rails/enum_hash.rb +3 -4
  47. data/lib/rubocop/cop/rails/enum_uniqueness.rb +3 -6
  48. data/lib/rubocop/cop/rails/environment_comparison.rb +3 -4
  49. data/lib/rubocop/cop/rails/environment_variable_access.rb +1 -1
  50. data/lib/rubocop/cop/rails/exit.rb +1 -1
  51. data/lib/rubocop/cop/rails/expanded_date_range.rb +39 -23
  52. data/lib/rubocop/cop/rails/file_path.rb +41 -24
  53. data/lib/rubocop/cop/rails/find_by.rb +1 -1
  54. data/lib/rubocop/cop/rails/find_by_id.rb +3 -3
  55. data/lib/rubocop/cop/rails/find_each.rb +14 -4
  56. data/lib/rubocop/cop/rails/freeze_time.rb +79 -0
  57. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +1 -1
  58. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +14 -8
  59. data/lib/rubocop/cop/rails/helper_instance_variable.rb +3 -3
  60. data/lib/rubocop/cop/rails/http_positional_arguments.rb +23 -12
  61. data/lib/rubocop/cop/rails/http_status.rb +6 -11
  62. data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +3 -1
  63. data/lib/rubocop/cop/rails/i18n_locale_assignment.rb +1 -1
  64. data/lib/rubocop/cop/rails/i18n_locale_texts.rb +2 -2
  65. data/lib/rubocop/cop/rails/ignored_columns_assignment.rb +50 -0
  66. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +5 -14
  67. data/lib/rubocop/cop/rails/index_by.rb +2 -2
  68. data/lib/rubocop/cop/rails/index_with.rb +2 -2
  69. data/lib/rubocop/cop/rails/inquiry.rb +1 -1
  70. data/lib/rubocop/cop/rails/inverse_of.rb +4 -10
  71. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +22 -16
  72. data/lib/rubocop/cop/rails/link_to_blank.rb +2 -5
  73. data/lib/rubocop/cop/rails/mailer_name.rb +5 -5
  74. data/lib/rubocop/cop/rails/match_route.rb +1 -1
  75. data/lib/rubocop/cop/rails/migration_class_name.rb +2 -2
  76. data/lib/rubocop/cop/rails/negate_include.rb +2 -2
  77. data/lib/rubocop/cop/rails/not_null_column.rb +10 -7
  78. data/lib/rubocop/cop/rails/order_by_id.rb +2 -3
  79. data/lib/rubocop/cop/rails/output.rb +7 -9
  80. data/lib/rubocop/cop/rails/output_safety.rb +6 -2
  81. data/lib/rubocop/cop/rails/pick.rb +1 -1
  82. data/lib/rubocop/cop/rails/pluck.rb +45 -13
  83. data/lib/rubocop/cop/rails/pluck_id.rb +2 -2
  84. data/lib/rubocop/cop/rails/pluck_in_where.rb +1 -1
  85. data/lib/rubocop/cop/rails/pluralization_grammar.rb +2 -3
  86. data/lib/rubocop/cop/rails/presence.rb +22 -13
  87. data/lib/rubocop/cop/rails/present.rb +10 -13
  88. data/lib/rubocop/cop/rails/rake_environment.rb +3 -3
  89. data/lib/rubocop/cop/rails/read_write_attribute.rb +2 -2
  90. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +5 -7
  91. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +3 -3
  92. data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +3 -3
  93. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +31 -27
  94. data/lib/rubocop/cop/rails/redundant_travel_back.rb +1 -1
  95. data/lib/rubocop/cop/rails/reflection_class_name.rb +35 -2
  96. data/lib/rubocop/cop/rails/refute_methods.rb +1 -5
  97. data/lib/rubocop/cop/rails/relative_date_constant.rb +5 -8
  98. data/lib/rubocop/cop/rails/render_inline.rb +1 -1
  99. data/lib/rubocop/cop/rails/render_plain_text.rb +1 -1
  100. data/lib/rubocop/cop/rails/request_referer.rb +2 -3
  101. data/lib/rubocop/cop/rails/require_dependency.rb +2 -2
  102. data/lib/rubocop/cop/rails/response_parsed_body.rb +57 -0
  103. data/lib/rubocop/cop/rails/reversible_migration.rb +15 -63
  104. data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +5 -6
  105. data/lib/rubocop/cop/rails/root_join_chain.rb +1 -1
  106. data/lib/rubocop/cop/rails/root_pathname_methods.rb +238 -0
  107. data/lib/rubocop/cop/rails/root_public_path.rb +59 -0
  108. data/lib/rubocop/cop/rails/safe_navigation.rb +8 -13
  109. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +2 -4
  110. data/lib/rubocop/cop/rails/save_bang.rb +12 -24
  111. data/lib/rubocop/cop/rails/schema_comment.rb +1 -1
  112. data/lib/rubocop/cop/rails/scope_args.rb +1 -1
  113. data/lib/rubocop/cop/rails/short_i18n.rb +3 -6
  114. data/lib/rubocop/cop/rails/skips_model_validations.rb +3 -4
  115. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +10 -7
  116. data/lib/rubocop/cop/rails/strip_heredoc.rb +56 -0
  117. data/lib/rubocop/cop/rails/table_name_assignment.rb +1 -1
  118. data/lib/rubocop/cop/rails/three_state_boolean_column.rb +73 -0
  119. data/lib/rubocop/cop/rails/time_zone.rb +34 -32
  120. data/lib/rubocop/cop/rails/time_zone_assignment.rb +4 -4
  121. data/lib/rubocop/cop/rails/to_formatted_s.rb +46 -0
  122. data/lib/rubocop/cop/rails/to_s_with_argument.rb +78 -0
  123. data/lib/rubocop/cop/rails/top_level_hash_with_indifferent_access.rb +49 -0
  124. data/lib/rubocop/cop/rails/transaction_exit_statement.rb +17 -12
  125. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +3 -6
  126. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +14 -7
  127. data/lib/rubocop/cop/rails/unknown_env.rb +3 -5
  128. data/lib/rubocop/cop/rails/unused_ignored_columns.rb +7 -2
  129. data/lib/rubocop/cop/rails/validation.rb +5 -13
  130. data/lib/rubocop/cop/rails/where_equals.rb +2 -2
  131. data/lib/rubocop/cop/rails/where_exists.rb +3 -3
  132. data/lib/rubocop/cop/rails/where_missing.rb +118 -0
  133. data/lib/rubocop/cop/rails/where_not.rb +2 -2
  134. data/lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb +55 -0
  135. data/lib/rubocop/cop/rails_cops.rb +16 -0
  136. data/lib/rubocop/rails/schema_loader/schema.rb +8 -5
  137. data/lib/rubocop/rails/version.rb +1 -1
  138. data/lib/rubocop/rails.rb +1 -1
  139. data/lib/rubocop-rails.rb +19 -0
  140. metadata +23 -9
  141. data/bin/console +0 -11
  142. data/bin/setup +0 -7
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop looks for `has_many` or `has_one` associations that don't
6
+ # Looks for `has_many` or `has_one` associations that don't
7
7
  # specify a `:dependent` option.
8
8
  #
9
9
  # It doesn't register an offense if `:through` or `dependent: nil`
@@ -37,15 +37,15 @@ module RuboCop
37
37
  RESTRICT_ON_SEND = %i[has_many has_one].freeze
38
38
 
39
39
  def_node_search :active_resource_class?, <<~PATTERN
40
- (const (const nil? :ActiveResource) :Base)
40
+ (const (const {nil? cbase} :ActiveResource) :Base)
41
41
  PATTERN
42
42
 
43
43
  def_node_matcher :association_without_options?, <<~PATTERN
44
- (send nil? {:has_many :has_one} _)
44
+ (send _ {:has_many :has_one} _)
45
45
  PATTERN
46
46
 
47
47
  def_node_matcher :association_with_options?, <<~PATTERN
48
- (send nil? {:has_many :has_one} ... (hash $...))
48
+ (send _ {:has_many :has_one} ... (hash $...))
49
49
  PATTERN
50
50
 
51
51
  def_node_matcher :dependent_option?, <<~PATTERN
@@ -105,9 +105,7 @@ module RuboCop
105
105
 
106
106
  return false unless node.parent
107
107
 
108
- return true if contain_valid_options_in_with_options_block?(
109
- node.parent.parent
110
- )
108
+ return true if contain_valid_options_in_with_options_block?(node.parent.parent)
111
109
  end
112
110
 
113
111
  false
@@ -116,7 +114,7 @@ module RuboCop
116
114
  def valid_options?(options)
117
115
  return false if options.nil?
118
116
 
119
- options = options.first.children.first.pairs if options.first.kwsplat_type?
117
+ options = extract_option_if_kwsplat(options)
120
118
 
121
119
  return true unless options
122
120
  return true if options.any? do |o|
@@ -126,6 +124,14 @@ module RuboCop
126
124
  false
127
125
  end
128
126
 
127
+ def extract_option_if_kwsplat(options)
128
+ if options.first.kwsplat_type? && options.first.children.first.hash_type?
129
+ return options.first.children.first.pairs
130
+ end
131
+
132
+ options
133
+ end
134
+
129
135
  def active_resource?(node)
130
136
  return false if node.nil?
131
137
 
@@ -3,14 +3,14 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop checks for use of the helper methods which reference
6
+ # Checks for use of the helper methods which reference
7
7
  # instance variables.
8
8
  #
9
9
  # Relying on instance variables makes it difficult to re-use helper
10
10
  # methods.
11
11
  #
12
12
  # If it seems awkward to explicitly pass in each dependent
13
- # variable, consider moving the behaviour elsewhere, for
13
+ # variable, consider moving the behavior elsewhere, for
14
14
  # example to a model, decorator or presenter.
15
15
  #
16
16
  # Provided that a class inherits `ActionView::Helpers::FormBuilder`,
@@ -37,7 +37,7 @@ module RuboCop
37
37
  def_node_matcher :form_builder_class?, <<~PATTERN
38
38
  (const
39
39
  (const
40
- (const nil? :ActionView) :Helpers) :FormBuilder)
40
+ (const {nil? cbase} :ActionView) :Helpers) :FormBuilder)
41
41
  PATTERN
42
42
 
43
43
  def on_ivar(node)
@@ -3,13 +3,16 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop is used to identify usages of http methods like `get`, `post`,
6
+ # Identifies usages of http methods like `get`, `post`,
7
7
  # `put`, `patch` without the usage of keyword arguments in your tests and
8
8
  # change them to use keyword args. This cop only applies to Rails >= 5.
9
9
  # If you are running Rails < 5 you should disable the
10
10
  # Rails/HttpPositionalArguments cop or set your TargetRailsVersion in your
11
11
  # .rubocop.yml file to 4.2.
12
12
  #
13
+ # NOTE: It does not detect any cases where `include Rack::Test::Methods` is used
14
+ # which makes the http methods incompatible behavior.
15
+ #
13
16
  # @example
14
17
  # # bad
15
18
  # get :new, { user_id: 1}
@@ -22,11 +25,8 @@ module RuboCop
22
25
  extend AutoCorrector
23
26
  extend TargetRailsVersion
24
27
 
25
- MSG = 'Use keyword arguments instead of ' \
26
- 'positional arguments for http call: `%<verb>s`.'
27
- KEYWORD_ARGS = %i[
28
- method params session body flash xhr as headers env to
29
- ].freeze
28
+ MSG = 'Use keyword arguments instead of positional arguments for http call: `%<verb>s`.'
29
+ KEYWORD_ARGS = %i[method params session body flash xhr as headers env to].freeze
30
30
  ROUTING_METHODS = %i[draw routes].freeze
31
31
  RESTRICT_ON_SEND = %i[get post put patch delete head].freeze
32
32
 
@@ -40,8 +40,15 @@ module RuboCop
40
40
  (hash (kwsplat _))
41
41
  PATTERN
42
42
 
43
+ def_node_matcher :include_rack_test_methods?, <<~PATTERN
44
+ (send nil? :include
45
+ (const
46
+ (const
47
+ (const {nil? cbase} :Rack) :Test) :Methods))
48
+ PATTERN
49
+
43
50
  def on_send(node)
44
- return if in_routing_block?(node)
51
+ return if in_routing_block?(node) || use_rack_test_methods?
45
52
 
46
53
  http_request?(node) do |data|
47
54
  return unless needs_conversion?(data)
@@ -59,7 +66,7 @@ module RuboCop
59
66
  # that represents the path/action on the Rails controller
60
67
  # the data is the http parameters and environment sent in
61
68
  # the Rails 5 http call
62
- corrector.replace(node.loc.expression, correction(node))
69
+ corrector.replace(node, correction(node))
63
70
  end
64
71
  end
65
72
  end
@@ -70,13 +77,18 @@ module RuboCop
70
77
  !!node.each_ancestor(:block).detect { |block| ROUTING_METHODS.include?(block.method_name) }
71
78
  end
72
79
 
80
+ def use_rack_test_methods?
81
+ processed_source.ast.each_descendant(:send).any? do |node|
82
+ include_rack_test_methods?(node)
83
+ end
84
+ end
85
+
73
86
  def needs_conversion?(data)
74
87
  return true unless data.hash_type?
75
88
  return false if kwsplat_hash?(data)
76
89
 
77
90
  data.each_pair.none? do |pair|
78
- special_keyword_arg?(pair.key) ||
79
- (format_arg?(pair.key) && data.pairs.one?)
91
+ special_keyword_arg?(pair.key) || (format_arg?(pair.key) && data.pairs.one?)
80
92
  end
81
93
  end
82
94
 
@@ -98,8 +110,7 @@ module RuboCop
98
110
  return '' if data.hash_type? && data.empty?
99
111
 
100
112
  hash_data = if data.hash_type?
101
- format('{ %<data>s }',
102
- data: data.pairs.map(&:source).join(', '))
113
+ format('{ %<data>s }', data: data.pairs.map(&:source).join(', '))
103
114
  else
104
115
  # user supplies an object,
105
116
  # no need to surround with braces
@@ -66,7 +66,7 @@ module RuboCop
66
66
  return unless checker.offensive?
67
67
 
68
68
  add_offense(checker.node, message: checker.message) do |corrector|
69
- corrector.replace(checker.node.loc.expression, checker.preferred_style)
69
+ corrector.replace(checker.node, checker.preferred_style)
70
70
  end
71
71
  end
72
72
  end
@@ -84,10 +84,8 @@ module RuboCop
84
84
 
85
85
  # :nodoc:
86
86
  class SymbolicStyleChecker
87
- MSG = 'Prefer `%<prefer>s` over `%<current>s` ' \
88
- 'to define HTTP status code.'
89
- DEFAULT_MSG = 'Prefer `symbolic` over `numeric` ' \
90
- 'to define HTTP status code.'
87
+ MSG = 'Prefer `%<prefer>s` over `%<current>s` to define HTTP status code.'
88
+ DEFAULT_MSG = 'Prefer `symbolic` over `numeric` to define HTTP status code.'
91
89
 
92
90
  attr_reader :node
93
91
 
@@ -118,17 +116,14 @@ module RuboCop
118
116
  end
119
117
 
120
118
  def custom_http_status_code?
121
- node.int_type? &&
122
- !::Rack::Utils::SYMBOL_TO_STATUS_CODE.value?(number)
119
+ node.int_type? && !::Rack::Utils::SYMBOL_TO_STATUS_CODE.value?(number)
123
120
  end
124
121
  end
125
122
 
126
123
  # :nodoc:
127
124
  class NumericStyleChecker
128
- MSG = 'Prefer `%<prefer>s` over `%<current>s` ' \
129
- 'to define HTTP status code.'
130
- DEFAULT_MSG = 'Prefer `numeric` over `symbolic` ' \
131
- 'to define HTTP status code.'
125
+ MSG = 'Prefer `%<prefer>s` over `%<current>s` to define HTTP status code.'
126
+ DEFAULT_MSG = 'Prefer `numeric` over `symbolic` to define HTTP status code.'
132
127
  PERMITTED_STATUS = %i[error success missing redirect].freeze
133
128
 
134
129
  attr_reader :node
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop checks for places where I18n "lazy" lookup can be used.
6
+ # Checks for places where I18n "lazy" lookup can be used.
7
7
  #
8
8
  # @example
9
9
  # # en.yml
@@ -34,6 +34,8 @@ module RuboCop
34
34
 
35
35
  MSG = 'Use "lazy" lookup for the text used in controllers.'
36
36
 
37
+ RESTRICT_ON_SEND = %i[translate t].freeze
38
+
37
39
  def_node_matcher :translate_call?, <<~PATTERN
38
40
  (send nil? {:translate :t} ${sym_type? str_type?} ...)
39
41
  PATTERN
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop checks for the use of `I18n.locale=` method.
6
+ # Checks for the use of `I18n.locale=` method.
7
7
  #
8
8
  # The `locale` attribute persists for the rest of the Ruby runtime, potentially causing
9
9
  # unexpected behavior at a later time.
@@ -69,7 +69,7 @@ module RuboCop
69
69
  class I18nLocaleTexts < Base
70
70
  MSG = 'Move locale texts to the locale files in the `config/locales` directory.'
71
71
 
72
- RESTRICT_ON_SEND = %i[validates redirect_to []= mail].freeze
72
+ RESTRICT_ON_SEND = %i[validates redirect_to redirect_back []= mail].freeze
73
73
 
74
74
  def_node_search :validation_message, <<~PATTERN
75
75
  (pair (sym :message) $str)
@@ -94,7 +94,7 @@ module RuboCop
94
94
  add_offense(text_node)
95
95
  end
96
96
  return
97
- when :redirect_to
97
+ when :redirect_to, :redirect_back
98
98
  text_node = redirect_to_flash(node).to_a.last
99
99
  when :[]=
100
100
  text_node = flash_assignment?(node)
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Looks for assignments of `ignored_columns` that may override previous
7
+ # assignments.
8
+ #
9
+ # Overwriting previous assignments is usually a mistake, since it will
10
+ # un-ignore the first set of columns. Since duplicate column names is not
11
+ # a problem, it is better to simply append to the list.
12
+ #
13
+ # @example
14
+ #
15
+ # # bad
16
+ # class User < ActiveRecord::Base
17
+ # self.ignored_columns = [:one]
18
+ # end
19
+ #
20
+ # # bad
21
+ # class User < ActiveRecord::Base
22
+ # self.ignored_columns = [:one, :two]
23
+ # end
24
+ #
25
+ # # good
26
+ # class User < ActiveRecord::Base
27
+ # self.ignored_columns += [:one, :two]
28
+ # end
29
+ #
30
+ # # good
31
+ # class User < ActiveRecord::Base
32
+ # self.ignored_columns += [:one]
33
+ # self.ignored_columns += [:two]
34
+ # end
35
+ #
36
+ class IgnoredColumnsAssignment < Base
37
+ extend AutoCorrector
38
+
39
+ MSG = 'Use `+=` instead of `=`.'
40
+ RESTRICT_ON_SEND = %i[ignored_columns=].freeze
41
+
42
+ def on_send(node)
43
+ add_offense(node.loc.operator) do |corrector|
44
+ corrector.replace(node.loc.operator, '+=')
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop checks that `if` and `only` (or `except`) are not used together
6
+ # Checks that `if` and `only` (or `except`) are not used together
7
7
  # as options of `skip_*` action filter.
8
8
  #
9
9
  # The `if` option will be ignored when `if` and `only` are used together.
@@ -35,19 +35,12 @@ module RuboCop
35
35
  # skip_before_action :login_required,
36
36
  # if: -> { trusted_origin? && action_name != "admin" }
37
37
  # end
38
- #
39
- # @see https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options
40
38
  class IgnoredSkipActionFilterOption < Base
41
39
  MSG = <<~MSG.chomp.freeze
42
40
  `%<ignore>s` option will be ignored when `%<prefer>s` and `%<ignore>s` are used together.
43
41
  MSG
44
42
 
45
- RESTRICT_ON_SEND = %i[
46
- skip_after_action
47
- skip_around_action
48
- skip_before_action
49
- skip_action_callback
50
- ].freeze
43
+ RESTRICT_ON_SEND = %i[skip_after_action skip_around_action skip_before_action skip_action_callback].freeze
51
44
 
52
45
  FILTERS = RESTRICT_ON_SEND.map { |method_name| ":#{method_name}" }
53
46
 
@@ -67,11 +60,9 @@ module RuboCop
67
60
  options = options_hash(options)
68
61
 
69
62
  if if_and_only?(options)
70
- add_offense(options[:if],
71
- message: format(MSG, prefer: :only, ignore: :if))
63
+ add_offense(options[:if], message: format(MSG, prefer: :only, ignore: :if))
72
64
  elsif if_and_except?(options)
73
- add_offense(options[:except],
74
- message: format(MSG, prefer: :if, ignore: :except))
65
+ add_offense(options[:except], message: format(MSG, prefer: :if, ignore: :except))
75
66
  end
76
67
  end
77
68
 
@@ -80,7 +71,7 @@ module RuboCop
80
71
  def options_hash(options)
81
72
  options.pairs
82
73
  .select { |pair| pair.key.sym_type? }
83
- .map { |pair| [pair.key.value, pair] }.to_h
74
+ .to_h { |pair| [pair.key.value, pair] }
84
75
  end
85
76
 
86
77
  def if_and_only?(options)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop looks for uses of `each_with_object({}) { ... }`,
6
+ # Looks for uses of `each_with_object({}) { ... }`,
7
7
  # `map { ... }.to_h`, and `Hash[map { ... }]` that are transforming
8
8
  # an enumerable into a hash where the values are the original elements.
9
9
  # Rails provides the `index_by` method for this purpose.
@@ -46,7 +46,7 @@ module RuboCop
46
46
 
47
47
  def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
48
48
  (send
49
- (const _ :Hash)
49
+ (const {nil? cbase} :Hash)
50
50
  :[]
51
51
  (block
52
52
  (call _ {:map :collect})
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop looks for uses of `each_with_object({}) { ... }`,
6
+ # Looks for uses of `each_with_object({}) { ... }`,
7
7
  # `map { ... }.to_h`, and `Hash[map { ... }]` that are transforming
8
8
  # an enumerable into a hash where the keys are the original elements.
9
9
  # Rails provides the `index_with` method for this purpose.
@@ -49,7 +49,7 @@ module RuboCop
49
49
 
50
50
  def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
51
51
  (send
52
- (const _ :Hash)
52
+ (const {nil? cbase} :Hash)
53
53
  :[]
54
54
  (block
55
55
  (call _ {:map :collect})
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop checks that Active Support's `inquiry` method is not used.
6
+ # Checks that Active Support's `inquiry` method is not used.
7
7
  #
8
8
  # @example
9
9
  # # bad - String#inquiry
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop looks for has_(one|many) and belongs_to associations where
6
+ # Looks for has_(one|many) and belongs_to associations where
7
7
  # Active Record can't automatically determine the inverse association
8
8
  # because of a scope or the options used. Using the blog with order scope
9
9
  # example below, traversing the a Blog's association in both directions
@@ -137,9 +137,6 @@ module RuboCop
137
137
  # class Blog < ApplicationRecord
138
138
  # has_many :posts, -> { order(published_at: :desc) }
139
139
  # end
140
- #
141
- # @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
142
- # @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
143
140
  class InverseOf < Base
144
141
  SPECIFY_MSG = 'Specify an `:inverse_of` option.'
145
142
  NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to use `inverse_of: false`.'
@@ -192,8 +189,7 @@ module RuboCop
192
189
  end
193
190
  return if options_ignoring_inverse_of?(options)
194
191
 
195
- return unless scope?(arguments) ||
196
- options_requiring_inverse_of?(options)
192
+ return unless scope?(arguments) || options_requiring_inverse_of?(options)
197
193
 
198
194
  return if options_contain_inverse_of?(options)
199
195
 
@@ -206,8 +202,7 @@ module RuboCop
206
202
 
207
203
  def options_requiring_inverse_of?(options)
208
204
  required = options.any? do |opt|
209
- conditions_option?(opt) ||
210
- foreign_key_option?(opt)
205
+ conditions_option?(opt) || foreign_key_option?(opt)
211
206
  end
212
207
 
213
208
  return required if target_rails_version >= 5.2
@@ -227,8 +222,7 @@ module RuboCop
227
222
 
228
223
  def with_options_arguments(recv, node)
229
224
  blocks = node.each_ancestor(:block).select do |block|
230
- block.send_node.command?(:with_options) &&
231
- same_context_in_with_options?(block.arguments.first, recv)
225
+ block.send_node.command?(:with_options) && same_context_in_with_options?(block.arguments.first, recv)
232
226
  end
233
227
  blocks.flat_map { |n| n.send_node.arguments }
234
228
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop checks that methods specified in the filter's `only` or
6
+ # Checks that methods specified in the filter's `only` or
7
7
  # `except` options are defined within the same class or module.
8
8
  #
9
9
  # @safety
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # methods that are defined in other classes or modules, you should
13
13
  # define the filter in that class or module.
14
14
  #
15
- # If you rely on behaviour defined in the superclass actions, you must
15
+ # If you rely on behavior defined in the superclass actions, you must
16
16
  # remember to invoke `super` in the subclass actions.
17
17
  #
18
18
  # @example
@@ -71,7 +71,7 @@ module RuboCop
71
71
  # class ArticlesController < ContentController
72
72
  # before_action :load_article, only: [:update]
73
73
  #
74
- # # the cop requires this method, but it relies on behaviour defined
74
+ # # the cop requires this method, but it relies on behavior defined
75
75
  # # in the superclass, so needs to invoke `super`
76
76
  # def update
77
77
  # super
@@ -144,19 +144,29 @@ module RuboCop
144
144
  end
145
145
 
146
146
  def aliased_action_methods(node, defined_methods)
147
- alias_methods = node.each_child_node(:send).select { |send_node| send_node.method?(:alias_method) }
148
-
149
- hash_of_alias_methods = alias_methods.each_with_object({}) do |alias_method, result|
150
- result[alias_method.last_argument.value] = alias_method.first_argument.value
151
- end
152
-
147
+ alias_methods = alias_methods(node)
153
148
  defined_methods.each_with_object([]) do |defined_method, aliased_method|
154
- if (new_method_name = hash_of_alias_methods[defined_method])
149
+ if (new_method_name = alias_methods[defined_method])
155
150
  aliased_method << new_method_name
156
151
  end
157
152
  end
158
153
  end
159
154
 
155
+ def alias_methods(node)
156
+ result = {}
157
+ node.each_child_node(:send, :alias) do |child_node|
158
+ case child_node.type
159
+ when :send
160
+ if child_node.method?(:alias_method)
161
+ result[child_node.last_argument.value] = child_node.first_argument.value
162
+ end
163
+ when :alias
164
+ result[child_node.old_identifier.value] = child_node.new_identifier.value
165
+ end
166
+ end
167
+ result
168
+ end
169
+
160
170
  # @param node [RuboCop::AST::Node]
161
171
  # @return [Array<Symbol>]
162
172
  def array_values(node) # rubocop:disable Metrics/MethodLength
@@ -184,13 +194,9 @@ module RuboCop
184
194
  # @return [String]
185
195
  def message(methods, parent)
186
196
  if methods.size == 1
187
- format(MSG,
188
- action: "`#{methods[0]}` is",
189
- type: parent.type)
197
+ format(MSG, action: "`#{methods[0]}` is", type: parent.type)
190
198
  else
191
- format(MSG,
192
- action: "`#{methods.join('`, `')}` are",
193
- type: parent.type)
199
+ format(MSG, action: "`#{methods.join('`, `')}` are", type: parent.type)
194
200
  end
195
201
  end
196
202
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop checks for calls to `link_to` that contain a
6
+ # Checks for calls to `link_to` that contain a
7
7
  # `target: '_blank'` but no `rel: 'noopener'`. This can be a security
8
8
  # risk as the loaded page will have control over the previous page
9
9
  # and could change its location for phishing purposes.
@@ -68,10 +68,7 @@ module RuboCop
68
68
 
69
69
  def append_to_rel(rel_node, corrector)
70
70
  existing_rel = rel_node.children.last.value
71
- str_range = rel_node.children.last.loc.expression.adjust(
72
- begin_pos: 1,
73
- end_pos: -1
74
- )
71
+ str_range = rel_node.children.last.source_range.adjust(begin_pos: 1, end_pos: -1)
75
72
  corrector.replace(str_range, "#{existing_rel} noopener")
76
73
  end
77
74
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop enforces that mailer names end with `Mailer` suffix.
6
+ # Enforces that mailer names end with `Mailer` suffix.
7
7
  #
8
8
  # Without the `Mailer` suffix it isn't immediately apparent what's a mailer
9
9
  # and which views are related to the mailer.
@@ -34,8 +34,8 @@ module RuboCop
34
34
 
35
35
  def_node_matcher :mailer_base_class?, <<~PATTERN
36
36
  {
37
- (const (const nil? :ActionMailer) :Base)
38
- (const nil? :ApplicationMailer)
37
+ (const (const {nil? cbase} :ActionMailer) :Base)
38
+ (const {nil? cbase} :ApplicationMailer)
39
39
  }
40
40
  PATTERN
41
41
 
@@ -44,7 +44,7 @@ module RuboCop
44
44
  PATTERN
45
45
 
46
46
  def_node_matcher :class_new_definition?, <<~PATTERN
47
- (send (const nil? :Class) :new #mailer_base_class?)
47
+ (send (const {nil? cbase} :Class) :new #mailer_base_class?)
48
48
  PATTERN
49
49
 
50
50
  def on_class(node)
@@ -77,7 +77,7 @@ module RuboCop
77
77
  corrector.replace(node.loc.name, "#{name}Mailer")
78
78
  else
79
79
  name = node.children.last
80
- corrector.replace(node.source_range, "#{name}Mailer")
80
+ corrector.replace(node, "#{name}Mailer")
81
81
  end
82
82
  end
83
83
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop identifies places where defining routes with `match`
6
+ # Identifies places where defining routes with `match`
7
7
  # can be replaced with a specific HTTP method.
8
8
  #
9
9
  # Don't use `match` to define any routes unless there is a need to map multiple request types
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop makes sure that each migration file defines a migration class
6
+ # Makes sure that each migration file defines a migration class
7
7
  # whose name matches the file name.
8
8
  # (e.g. `20220224111111_create_users.rb` should define `CreateUsers` class.)
9
9
  #
@@ -29,7 +29,7 @@ module RuboCop
29
29
 
30
30
  basename = basename_without_timestamp_and_suffix(processed_source.file_path)
31
31
 
32
- class_identifier = node.identifier
32
+ class_identifier = node.identifier.location.name
33
33
  camelized_basename = camelize(basename)
34
34
  return if class_identifier.source.casecmp(camelized_basename).zero?
35
35
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cop enforces the use of `collection.exclude?(obj)`
6
+ # Enforces the use of `collection.exclude?(obj)`
7
7
  # over `!collection.include?(obj)`.
8
8
  #
9
9
  # @safety
@@ -26,7 +26,7 @@ module RuboCop
26
26
  RESTRICT_ON_SEND = %i[!].freeze
27
27
 
28
28
  def_node_matcher :negate_include_call?, <<~PATTERN
29
- (send (send $_ :include? $_) :!)
29
+ (send (send $!nil? :include? $_) :!)
30
30
  PATTERN
31
31
 
32
32
  def on_send(node)