rubocop-rails 2.18.0 → 2.19.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -2
  3. data/config/default.yml +13 -13
  4. data/lib/rubocop/cop/mixin/enforce_superclass.rb +1 -1
  5. data/lib/rubocop/cop/mixin/index_method.rb +3 -3
  6. data/lib/rubocop/cop/rails/action_order.rb +5 -6
  7. data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +6 -3
  8. data/lib/rubocop/cop/rails/add_column_index.rb +2 -2
  9. data/lib/rubocop/cop/rails/application_job.rb +1 -1
  10. data/lib/rubocop/cop/rails/arel_star.rb +1 -1
  11. data/lib/rubocop/cop/rails/assert_not.rb +1 -1
  12. data/lib/rubocop/cop/rails/belongs_to.rb +1 -1
  13. data/lib/rubocop/cop/rails/blank.rb +4 -4
  14. data/lib/rubocop/cop/rails/compact_blank.rb +2 -2
  15. data/lib/rubocop/cop/rails/content_tag.rb +1 -1
  16. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +16 -3
  17. data/lib/rubocop/cop/rails/delegate.rb +17 -3
  18. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +1 -1
  19. data/lib/rubocop/cop/rails/duration_arithmetic.rb +1 -1
  20. data/lib/rubocop/cop/rails/dynamic_find_by.rb +1 -1
  21. data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +1 -1
  22. data/lib/rubocop/cop/rails/enum_hash.rb +1 -1
  23. data/lib/rubocop/cop/rails/environment_comparison.rb +1 -1
  24. data/lib/rubocop/cop/rails/file_path.rb +31 -15
  25. data/lib/rubocop/cop/rails/find_by_id.rb +2 -2
  26. data/lib/rubocop/cop/rails/find_each.rb +6 -2
  27. data/lib/rubocop/cop/rails/http_positional_arguments.rb +18 -2
  28. data/lib/rubocop/cop/rails/http_status.rb +1 -1
  29. data/lib/rubocop/cop/rails/link_to_blank.rb +1 -1
  30. data/lib/rubocop/cop/rails/mailer_name.rb +1 -1
  31. data/lib/rubocop/cop/rails/output.rb +3 -2
  32. data/lib/rubocop/cop/rails/output_safety.rb +5 -1
  33. data/lib/rubocop/cop/rails/pluck.rb +1 -1
  34. data/lib/rubocop/cop/rails/pluck_id.rb +1 -1
  35. data/lib/rubocop/cop/rails/presence.rb +1 -1
  36. data/lib/rubocop/cop/rails/present.rb +4 -4
  37. data/lib/rubocop/cop/rails/rake_environment.rb +1 -1
  38. data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -1
  39. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +3 -3
  40. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
  41. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
  42. data/lib/rubocop/cop/rails/reflection_class_name.rb +17 -1
  43. data/lib/rubocop/cop/rails/relative_date_constant.rb +2 -2
  44. data/lib/rubocop/cop/rails/response_parsed_body.rb +3 -3
  45. data/lib/rubocop/cop/rails/root_join_chain.rb +1 -1
  46. data/lib/rubocop/cop/rails/root_pathname_methods.rb +1 -1
  47. data/lib/rubocop/cop/rails/safe_navigation.rb +1 -1
  48. data/lib/rubocop/cop/rails/three_state_boolean_column.rb +73 -0
  49. data/lib/rubocop/cop/rails/time_zone.rb +2 -2
  50. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -1
  51. data/lib/rubocop/cop/rails/validation.rb +1 -1
  52. data/lib/rubocop/cop/rails/where_equals.rb +1 -1
  53. data/lib/rubocop/cop/rails/where_exists.rb +1 -1
  54. data/lib/rubocop/cop/rails/where_missing.rb +3 -3
  55. data/lib/rubocop/cop/rails/where_not.rb +1 -1
  56. data/lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb +2 -2
  57. data/lib/rubocop/cop/rails_cops.rb +1 -0
  58. data/lib/rubocop/rails/version.rb +1 -1
  59. data/lib/rubocop-rails.rb +1 -0
  60. metadata +5 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f1cbc229165ee81ea84fc26d1c6482f917d8e8177827b139cf36974acff0176
4
- data.tar.gz: 23cefe2f0434e5ef4c86856221f1336bfc55ffbacfd09f2dc9a24552b633d355
3
+ metadata.gz: b020fcc0db6203c33dfe23032cc2c6ec0df139e6abb048409bdf7439ea2d4183
4
+ data.tar.gz: fc6e892161124d21b9067e01e6b86178857df27d14ae687f3f0fdcceb2b3d078
5
5
  SHA512:
6
- metadata.gz: 59f9af07f060ff82a64bbf9db4af4d8ebb56dfada8310073bca25fde87736ef8fa0891e6f3ba997e8b847eef6218d93f25739b8022a8cb68e9aae970e8b2c674
7
- data.tar.gz: a4415117082d7ccaeb8349f1ee31c9dba95bb6ea54bed77b176bcdd59b03cf4e2702f99c05414ff1e9028c48f96dce2f729eb2a2b98f91183cba3cb143e08894
6
+ metadata.gz: f09636066a282111462ab5cc3b93463ec0cd8a111e2882b6e7c21889da3b36958766f722926418439e48933d8791ce41c0edadc3e4a590c5f8caeb82f35ad5b1
7
+ data.tar.gz: 40586400ad94701ee39ee71ab7280f7328889245f4786503cf5a851d158a05e4f736eea42c53f61164a420af8fab7e19854c6302237115a29efd3bdd1f19cc68
data/README.md CHANGED
@@ -12,7 +12,7 @@ Note: This repository manages rubocop-rails gem (>= 2.0.0). rubocop-rails gem (<
12
12
  Just install the `rubocop-rails` gem
13
13
 
14
14
  ```sh
15
- gem install rubocop-rails
15
+ $ gem install rubocop-rails
16
16
  ```
17
17
 
18
18
  or if you use bundler put this in your `Gemfile`
@@ -48,7 +48,7 @@ cops together with the standard cops.
48
48
  ### Command line
49
49
 
50
50
  ```sh
51
- rubocop --require rubocop-rails
51
+ $ rubocop --require rubocop-rails
52
52
  ```
53
53
 
54
54
  Note: `--rails` option is required while `rubocop` command supports `--rails` option.
@@ -61,6 +61,27 @@ RuboCop::RakeTask.new do |task|
61
61
  end
62
62
  ```
63
63
 
64
+ ## Rails configuration tip
65
+
66
+ If you are using Rails 6.1 or newer, add the following `config.generators.after_generate` setting to
67
+ your config/application.rb to apply RuboCop autocorrection to code generated by `bin/rails g`.
68
+
69
+ ```ruby
70
+ # config/application.rb
71
+ module YourCoolApp
72
+ class Application < Rails::Application
73
+ config.generators.after_generate do |files|
74
+ parsable_files = files.filter { |file| file.end_with?('.rb') }
75
+ system("bundle exec rubocop -A --fail-level=E #{parsable_files.shelljoin}", exception: true)
76
+ end
77
+ end
78
+ end
79
+ ```
80
+
81
+ It uses `rubocop -A` to apply `Style/FrozenStringLiteralComment` and other unsafe autocorretion cops.
82
+ `rubocop -A` is unsafe autocorrection, but code generated by default is simple and less likely to
83
+ be incompatible with `rubocop -A`. If you have problems you can replace it with `rubocop -a` instead.
84
+
64
85
  ## The Cops
65
86
 
66
87
  All cops are located under
data/config/default.yml CHANGED
@@ -53,8 +53,6 @@ Rails:
53
53
 
54
54
  Rails/ActionControllerFlashBeforeRender:
55
55
  Description: 'Use `flash.now` instead of `flash` before `render`.'
56
- StyleGuide: 'https://rails.rubystyle.guide/#flash-before-render'
57
- Reference: 'https://api.rubyonrails.org/classes/ActionController/FlashBeforeRender.html'
58
56
  Enabled: 'pending'
59
57
  SafeAutoCorrect: false
60
58
  VersionAdded: '2.16'
@@ -462,8 +460,9 @@ Rails/FindEach:
462
460
  Description: 'Prefer all.find_each over all.each.'
463
461
  StyleGuide: 'https://rails.rubystyle.guide#find-each'
464
462
  Enabled: true
463
+ Safe: false
465
464
  VersionAdded: '0.30'
466
- VersionChanged: '2.9'
465
+ VersionChanged: '2.19'
467
466
  Include:
468
467
  - app/models/**/*.rb
469
468
  AllowedMethods:
@@ -844,8 +843,9 @@ Rails/RequireDependency:
844
843
  Rails/ResponseParsedBody:
845
844
  Description: Prefer `response.parsed_body` to `JSON.parse(response.body)`.
846
845
  Enabled: pending
847
- SafeAutoCorrect: false
846
+ Safe: false
848
847
  VersionAdded: '2.18'
848
+ VersionChanged: '2.19'
849
849
  Include:
850
850
  - spec/controllers/**/*.rb
851
851
  - spec/requests/**/*.rb
@@ -997,6 +997,14 @@ Rails/TableNameAssignment:
997
997
  Include:
998
998
  - app/models/**/*.rb
999
999
 
1000
+ Rails/ThreeStateBooleanColumn:
1001
+ Description: 'Add a default value and a `NOT NULL` constraint to boolean columns.'
1002
+ StyleGuide: 'https://rails.rubystyle.guide/#three-state-boolean'
1003
+ Enabled: pending
1004
+ VersionAdded: '2.19'
1005
+ Include:
1006
+ - db/**/*.rb
1007
+
1000
1008
  Rails/TimeZone:
1001
1009
  Description: 'Checks the correct usage of time zone aware methods.'
1002
1010
  StyleGuide: 'https://rails.rubystyle.guide#time'
@@ -1131,6 +1139,7 @@ Rails/WhereNot:
1131
1139
 
1132
1140
  Rails/WhereNotWithMultipleConditions:
1133
1141
  Description: 'Do not use `where.not(...)` with multiple conditions.'
1142
+ StyleGuide: 'https://rails.rubystyle.guide/#where-not-with-multiple-attributes'
1134
1143
  Enabled: 'pending'
1135
1144
  Severity: warning
1136
1145
  VersionAdded: '2.17'
@@ -1144,15 +1153,6 @@ Style/FormatStringToken:
1144
1153
  AllowedMethods:
1145
1154
  - redirect
1146
1155
 
1147
- Style/InverseMethods:
1148
- # `InverseMethods` are methods that can be inverted by a not (`not` or `!`)
1149
- # The relationship of inverse methods only needs to be defined in one direction.
1150
- # Keys and values both need to be defined as symbols.
1151
- InverseMethods:
1152
- :present?: :blank?
1153
- :include?: :exclude?
1154
- :valid?: :invalid?
1155
-
1156
1156
  Style/SymbolProc:
1157
1157
  AllowedMethods:
1158
1158
  - define_method
@@ -32,7 +32,7 @@ module RuboCop
32
32
 
33
33
  def register_offense(offense_node)
34
34
  add_offense(offense_node) do |corrector|
35
- corrector.replace(offense_node.source_range, self.class::SUPERCLASS)
35
+ corrector.replace(offense_node, self.class::SUPERCLASS)
36
36
  end
37
37
  end
38
38
  end
@@ -138,7 +138,7 @@ module RuboCop
138
138
  end
139
139
 
140
140
  def strip_prefix_and_suffix(node, corrector)
141
- expression = node.loc.expression
141
+ expression = node.source_range
142
142
  corrector.remove_leading(expression, leading)
143
143
  corrector.remove_trailing(expression, trailing)
144
144
  end
@@ -153,11 +153,11 @@ module RuboCop
153
153
  end
154
154
 
155
155
  def set_new_arg_name(transformed_argname, corrector)
156
- corrector.replace(block_node.arguments.loc.expression, "|#{transformed_argname}|")
156
+ corrector.replace(block_node.arguments, "|#{transformed_argname}|")
157
157
  end
158
158
 
159
159
  def set_new_body_expression(transforming_body_expr, corrector)
160
- corrector.replace(block_node.body.loc.expression, transforming_body_expr.loc.expression.source)
160
+ corrector.replace(block_node.body, transforming_body_expr.source)
161
161
  end
162
162
  end
163
163
  end
@@ -92,12 +92,11 @@ module RuboCop
92
92
  end
93
93
 
94
94
  def range_with_comments(node)
95
- ranges = [
96
- node,
97
- *processed_source.ast_with_comments[node]
98
- ].map do |element|
99
- element.location.expression
100
- end
95
+ # rubocop:todo InternalAffairs/LocationExpression
96
+ # Using `RuboCop::Ext::Comment#source_range` requires RuboCop > 1.46,
97
+ # which introduces https://github.com/rubocop/rubocop/pull/11630.
98
+ ranges = [node, *processed_source.ast_with_comments[node]].map { |comment| comment.loc.expression }
99
+ # rubocop:enable InternalAffairs/LocationExpression
101
100
  ranges.reduce do |result, range|
102
101
  add_range(result, range)
103
102
  end
@@ -104,7 +104,7 @@ module RuboCop
104
104
  end
105
105
 
106
106
  def end_position_for(node)
107
- end_line = buffer.line_for_position(node.loc.expression.end_pos)
107
+ end_line = buffer.line_for_position(node.source_range.end_pos)
108
108
  buffer.line_range(end_line).end_pos
109
109
  end
110
110
 
@@ -112,8 +112,7 @@ module RuboCop
112
112
  annotation_line = node.first_line - 1
113
113
  first_comment = nil
114
114
 
115
- processed_source.comments_before_line(annotation_line)
116
- .reverse_each do |comment|
115
+ processed_source.each_comment_in_lines(0..annotation_line).reverse_each do |comment|
117
116
  if comment.location.line == annotation_line && !inline_comment?(comment)
118
117
  first_comment = comment
119
118
  annotation_line -= 1
@@ -124,7 +123,11 @@ module RuboCop
124
123
  end
125
124
 
126
125
  def inline_comment?(comment)
126
+ # rubocop:todo InternalAffairs/LocationExpression
127
+ # Using `RuboCop::Ext::Comment#source_range` requires RuboCop > 1.46,
128
+ # which introduces https://github.com/rubocop/rubocop/pull/11630.
127
129
  !comment_line?(comment.loc.expression.source_line)
130
+ # rubocop:enable InternalAffairs/LocationExpression
128
131
  end
129
132
 
130
133
  def start_line_position(node)
@@ -42,7 +42,7 @@ module RuboCop
42
42
  add_index_opts = ''
43
43
 
44
44
  if value.hash_type?
45
- hash = value.loc.expression.adjust(begin_pos: 1, end_pos: -1).source.strip
45
+ hash = value.source_range.adjust(begin_pos: 1, end_pos: -1).source.strip
46
46
  add_index_opts = ", #{hash}"
47
47
  end
48
48
 
@@ -53,7 +53,7 @@ module RuboCop
53
53
  private
54
54
 
55
55
  def index_range(pair_node)
56
- range_with_surrounding_comma(range_with_surrounding_space(pair_node.loc.expression, side: :left), :left)
56
+ range_with_surrounding_comma(range_with_surrounding_space(pair_node.source_range, side: :left), :left)
57
57
  end
58
58
  end
59
59
  end
@@ -36,7 +36,7 @@ module RuboCop
36
36
 
37
37
  def autocorrect(node)
38
38
  lambda do |corrector|
39
- corrector.replace(node.source_range, self.class::SUPERCLASS)
39
+ corrector.replace(node, self.class::SUPERCLASS)
40
40
  end
41
41
  end
42
42
  end
@@ -38,7 +38,7 @@ module RuboCop
38
38
  return unless (star = star_bracket?(node))
39
39
 
40
40
  add_offense(star) do |corrector|
41
- corrector.replace(star.loc.expression, 'Arel.star')
41
+ corrector.replace(star, 'Arel.star')
42
42
  end
43
43
  end
44
44
  end
@@ -25,7 +25,7 @@ module RuboCop
25
25
  return unless offensive?(node)
26
26
 
27
27
  add_offense(node) do |corrector|
28
- expression = node.loc.expression
28
+ expression = node.source_range
29
29
 
30
30
  corrector.replace(expression, corrected_source(expression.source))
31
31
  end
@@ -80,7 +80,7 @@ module RuboCop
80
80
  end
81
81
 
82
82
  add_offense(node.loc.selector, message: message) do |corrector|
83
- corrector.replace(option_node.loc.expression, replacement)
83
+ corrector.replace(option_node, replacement)
84
84
  end
85
85
  end
86
86
  end
@@ -142,10 +142,10 @@ module RuboCop
142
142
 
143
143
  if method_call
144
144
  corrector.replace(node.loc.keyword, 'if')
145
- range = method_call.loc.expression
145
+ range = method_call.source_range
146
146
  else
147
147
  variable1, _variable2 = nil_or_empty?(node) || not_present?(node)
148
- range = node.loc.expression
148
+ range = node.source_range
149
149
  end
150
150
 
151
151
  corrector.replace(range, replacement(variable1))
@@ -153,9 +153,9 @@ module RuboCop
153
153
 
154
154
  def unless_condition(node, method_call)
155
155
  if node.modifier_form?
156
- node.loc.keyword.join(node.loc.expression.end)
156
+ node.loc.keyword.join(node.source_range.end)
157
157
  else
158
- node.loc.expression.begin.join(method_call.loc.expression)
158
+ node.source_range.begin.join(method_call.source_range)
159
159
  end
160
160
  end
161
161
 
@@ -94,9 +94,9 @@ module RuboCop
94
94
 
95
95
  def offense_range(node)
96
96
  end_pos = if node.parent&.block_type? && node.parent&.send_node == node
97
- node.parent.loc.expression.end_pos
97
+ node.parent.source_range.end_pos
98
98
  else
99
- node.loc.expression.end_pos
99
+ node.source_range.end_pos
100
100
  end
101
101
 
102
102
  range_between(node.loc.selector.begin_pos, end_pos)
@@ -85,7 +85,7 @@ module RuboCop
85
85
  end
86
86
 
87
87
  def correction_range(node)
88
- range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
88
+ range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
89
89
  end
90
90
  end
91
91
  end
@@ -3,10 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # Checks the migration for which timestamps are not included
7
- # when creating a new table.
6
+ # Checks the migration for which timestamps are not included when creating a new table.
8
7
  # In many cases, timestamps are useful information and should be added.
9
8
  #
9
+ # NOTE: Allow `timestamps` not written when `id: false` because this emphasizes respecting
10
+ # user's editing intentions.
11
+ #
10
12
  # @example
11
13
  # # bad
12
14
  # create_table :users
@@ -40,12 +42,23 @@ module RuboCop
40
42
  #
41
43
  # t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP' }
42
44
  # end
45
+ #
46
+ # # good
47
+ # create_table :users, articles, id: false do |t|
48
+ # t.integer :user_id
49
+ # t.integer :article_id
50
+ # end
51
+ #
43
52
  class CreateTableWithTimestamps < Base
44
53
  include ActiveRecordMigrationsHelper
45
54
 
46
55
  MSG = 'Add timestamps when creating a new table.'
47
56
  RESTRICT_ON_SEND = %i[create_table].freeze
48
57
 
58
+ def_node_search :use_id_false_option?, <<~PATTERN
59
+ (pair (sym :id) (false))
60
+ PATTERN
61
+
49
62
  def_node_matcher :create_table_with_timestamps_proc?, <<~PATTERN
50
63
  (send nil? :create_table (sym _) ... (block-pass (sym :timestamps)))
51
64
  PATTERN
@@ -61,7 +74,7 @@ module RuboCop
61
74
  PATTERN
62
75
 
63
76
  def on_send(node)
64
- return unless node.command?(:create_table)
77
+ return if !node.command?(:create_table) || use_id_false_option?(node)
65
78
 
66
79
  parent = node.parent
67
80
 
@@ -24,6 +24,14 @@ module RuboCop
24
24
  # # good
25
25
  # delegate :bar, to: :foo
26
26
  #
27
+ # # bad
28
+ # def bar
29
+ # self.bar
30
+ # end
31
+ #
32
+ # # good
33
+ # delegate :bar, to: :self
34
+ #
27
35
  # # good
28
36
  # def bar
29
37
  # foo&.bar
@@ -60,7 +68,7 @@ module RuboCop
60
68
 
61
69
  def_node_matcher :delegate?, <<~PATTERN
62
70
  (def _method_name _args
63
- (send (send nil? _) _ ...))
71
+ (send {(send nil? _) (self)} _ ...))
64
72
  PATTERN
65
73
 
66
74
  def on_def(node)
@@ -74,10 +82,14 @@ module RuboCop
74
82
 
75
83
  def register_offense(node)
76
84
  add_offense(node.loc.keyword) do |corrector|
77
- delegation = ["delegate :#{node.body.method_name}", "to: :#{node.body.receiver.method_name}"]
85
+ body = node.body
86
+
87
+ receiver = body.receiver.self_type? ? 'self' : ":#{body.receiver.method_name}"
88
+
89
+ delegation = ["delegate :#{body.method_name}", "to: #{receiver}"]
78
90
  delegation << ['prefix: true'] if node.method?(prefixed_method_name(node.body))
79
91
 
80
- corrector.replace(node.source_range, delegation.join(', '))
92
+ corrector.replace(node, delegation.join(', '))
81
93
  end
82
94
  end
83
95
 
@@ -106,6 +118,8 @@ module RuboCop
106
118
  end
107
119
 
108
120
  def prefixed_method_name(body)
121
+ return '' if body.receiver.self_type?
122
+
109
123
  [body.receiver.method_name, body.method_name].join('_').to_sym
110
124
  end
111
125
 
@@ -27,7 +27,7 @@ module RuboCop
27
27
  return unless (offending_node = allow_blank_option(node))
28
28
 
29
29
  add_offense(offending_node) do |corrector|
30
- corrector.replace(offending_node.key.source_range, 'allow_nil')
30
+ corrector.replace(offending_node.key, 'allow_nil')
31
31
  end
32
32
  end
33
33
  end
@@ -78,7 +78,7 @@ module RuboCop
78
78
  def on_send(node)
79
79
  duration_arithmetic_argument?(node) do |*operation|
80
80
  add_offense(node) do |corrector|
81
- corrector.replace(node.source_range, corrected_source(*operation))
81
+ corrector.replace(node, corrected_source(*operation))
82
82
  end
83
83
  end
84
84
  end
@@ -99,7 +99,7 @@ module RuboCop
99
99
 
100
100
  def autocorrect_argument_keywords(corrector, node, keywords)
101
101
  keywords.each.with_index do |keyword, idx|
102
- corrector.insert_before(node.arguments[idx].loc.expression, keyword)
102
+ corrector.insert_before(node.arguments[idx], keyword)
103
103
  end
104
104
  end
105
105
 
@@ -59,7 +59,7 @@ module RuboCop
59
59
  private
60
60
 
61
61
  def replacement_range(node)
62
- stop = node.loc.expression.end
62
+ stop = node.source_range.end
63
63
  start = node.loc.selector.end
64
64
 
65
65
  if node.parenthesized_call?
@@ -42,7 +42,7 @@ module RuboCop
42
42
  "#{source(elem)} => #{index}"
43
43
  end.join(', ')
44
44
 
45
- corrector.replace(array.loc.expression, "{#{hash}}")
45
+ corrector.replace(array, "{#{hash}}")
46
46
  end
47
47
  end
48
48
  end
@@ -84,7 +84,7 @@ module RuboCop
84
84
  def autocorrect(corrector, node)
85
85
  replacement = build_predicate_method(node)
86
86
 
87
- corrector.replace(node.source_range, replacement)
87
+ corrector.replace(node, replacement)
88
88
  end
89
89
 
90
90
  def build_predicate_method(node)
@@ -3,34 +3,43 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # Identifies usages of file path joining process
7
- # to use `Rails.root.join` clause. It is used to add uniformity when
8
- # joining paths.
6
+ # Identifies usages of file path joining process to use `Rails.root.join` clause.
7
+ # It is used to add uniformity when joining paths.
9
8
  #
10
9
  # @example EnforcedStyle: slashes (default)
11
10
  # # bad
12
11
  # Rails.root.join('app', 'models', 'goober')
12
+ #
13
+ # # good
14
+ # Rails.root.join('app/models/goober')
15
+ #
16
+ # # bad
13
17
  # File.join(Rails.root, 'app/models/goober')
14
18
  # "#{Rails.root}/app/models/goober"
15
19
  #
16
20
  # # good
17
- # Rails.root.join('app/models/goober')
21
+ # Rails.root.join('app/models/goober').to_s
18
22
  #
19
23
  # @example EnforcedStyle: arguments
20
24
  # # bad
21
25
  # Rails.root.join('app/models/goober')
26
+ #
27
+ # # good
28
+ # Rails.root.join('app', 'models', 'goober')
29
+ #
30
+ # # bad
22
31
  # File.join(Rails.root, 'app/models/goober')
23
32
  # "#{Rails.root}/app/models/goober"
24
33
  #
25
34
  # # good
26
- # Rails.root.join('app', 'models', 'goober')
35
+ # Rails.root.join('app', 'models', 'goober').to_s
27
36
  #
28
37
  class FilePath < Base
29
38
  include ConfigurableEnforcedStyle
30
39
  include RangeHelp
31
40
 
32
- MSG_SLASHES = 'Prefer `Rails.root.join(\'path/to\')`.'
33
- MSG_ARGUMENTS = 'Prefer `Rails.root.join(\'path\', \'to\')`.'
41
+ MSG_SLASHES = 'Prefer `Rails.root.join(\'path/to\')%<to_s>s`.'
42
+ MSG_ARGUMENTS = 'Prefer `Rails.root.join(\'path\', \'to\')%<to_s>s`.'
34
43
  RESTRICT_ON_SEND = %i[join].freeze
35
44
 
36
45
  def_node_matcher :file_join_nodes?, <<~PATTERN
@@ -53,7 +62,7 @@ module RuboCop
53
62
  return unless last_child_source.start_with?('.') || last_child_source.include?(File::SEPARATOR)
54
63
  return if last_child_source.start_with?(':')
55
64
 
56
- register_offense(node)
65
+ register_offense(node, require_to_s: true)
57
66
  end
58
67
 
59
68
  def on_send(node)
@@ -68,7 +77,7 @@ module RuboCop
68
77
  return unless file_join_nodes?(node)
69
78
  return unless node.arguments.any? { |e| rails_root_nodes?(e) }
70
79
 
71
- register_offense(node)
80
+ register_offense(node, require_to_s: true)
72
81
  end
73
82
 
74
83
  def check_for_rails_root_join_with_string_arguments(node)
@@ -78,7 +87,7 @@ module RuboCop
78
87
  return unless node.arguments.size > 1
79
88
  return unless node.arguments.all?(&:str_type?)
80
89
 
81
- register_offense(node)
90
+ register_offense(node, require_to_s: false)
82
91
  end
83
92
 
84
93
  def check_for_rails_root_join_with_slash_separated_path(node)
@@ -87,21 +96,28 @@ module RuboCop
87
96
  return unless rails_root_join_nodes?(node)
88
97
  return unless node.arguments.any? { |arg| string_with_slash?(arg) }
89
98
 
90
- register_offense(node)
99
+ register_offense(node, require_to_s: false)
91
100
  end
92
101
 
93
102
  def string_with_slash?(node)
94
103
  node.str_type? && node.source.include?('/')
95
104
  end
96
105
 
97
- def register_offense(node)
106
+ def register_offense(node, require_to_s:)
98
107
  line_range = node.loc.column...node.loc.last_column
99
108
  source_range = source_range(processed_source.buffer, node.first_line, line_range)
100
- add_offense(source_range)
109
+ require_to_s = false if node.dstr_type?
110
+
111
+ message = build_message(require_to_s)
112
+
113
+ add_offense(source_range, message: message)
101
114
  end
102
115
 
103
- def message(_range)
104
- format(style == :arguments ? MSG_ARGUMENTS : MSG_SLASHES)
116
+ def build_message(require_to_s)
117
+ message_template = style == :arguments ? MSG_ARGUMENTS : MSG_SLASHES
118
+ to_s = require_to_s ? '.to_s' : ''
119
+
120
+ format(message_template, to_s: to_s)
105
121
  end
106
122
  end
107
123
  end
@@ -65,11 +65,11 @@ module RuboCop
65
65
  end
66
66
 
67
67
  def where_take_offense_range(node, where)
68
- range_between(where.loc.selector.begin_pos, node.loc.expression.end_pos)
68
+ range_between(where.loc.selector.begin_pos, node.source_range.end_pos)
69
69
  end
70
70
 
71
71
  def find_by_offense_range(node)
72
- range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
72
+ range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
73
73
  end
74
74
 
75
75
  def build_good_method(id_value)
@@ -3,8 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # Identifies usages of `all.each` and
7
- # change them to use `all.find_each` instead.
6
+ # Identifies usages of `all.each` and change them to use `all.find_each` instead.
7
+ #
8
+ # @safety
9
+ # This cop is unsafe if the receiver object is not an Active Record object.
10
+ # Also, `all.each` returns an `Array` instance and `all.find_each` returns nil,
11
+ # so the return values are different.
8
12
  #
9
13
  # @example
10
14
  # # bad
@@ -10,6 +10,9 @@ module RuboCop
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}
@@ -37,8 +40,15 @@ module RuboCop
37
40
  (hash (kwsplat _))
38
41
  PATTERN
39
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
+
40
50
  def on_send(node)
41
- return if in_routing_block?(node)
51
+ return if in_routing_block?(node) || use_rack_test_methods?
42
52
 
43
53
  http_request?(node) do |data|
44
54
  return unless needs_conversion?(data)
@@ -56,7 +66,7 @@ module RuboCop
56
66
  # that represents the path/action on the Rails controller
57
67
  # the data is the http parameters and environment sent in
58
68
  # the Rails 5 http call
59
- corrector.replace(node.loc.expression, correction(node))
69
+ corrector.replace(node, correction(node))
60
70
  end
61
71
  end
62
72
  end
@@ -67,6 +77,12 @@ module RuboCop
67
77
  !!node.each_ancestor(:block).detect { |block| ROUTING_METHODS.include?(block.method_name) }
68
78
  end
69
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
+
70
86
  def needs_conversion?(data)
71
87
  return true unless data.hash_type?
72
88
  return false if kwsplat_hash?(data)
@@ -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
@@ -68,7 +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(begin_pos: 1, end_pos: -1)
71
+ str_range = rel_node.children.last.source_range.adjust(begin_pos: 1, end_pos: -1)
72
72
  corrector.replace(str_range, "#{existing_rel} noopener")
73
73
  end
74
74
 
@@ -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
 
@@ -39,7 +39,8 @@ module RuboCop
39
39
  PATTERN
40
40
 
41
41
  def on_send(node)
42
- return unless (output?(node) || io_output?(node)) && node.arguments?
42
+ return if node.parent&.call_type?
43
+ return unless output?(node) || io_output?(node)
43
44
 
44
45
  range = offense_range(node)
45
46
 
@@ -56,7 +57,7 @@ module RuboCop
56
57
 
57
58
  def offense_range(node)
58
59
  if node.receiver
59
- range_between(node.loc.expression.begin_pos, node.loc.selector.end_pos)
60
+ range_between(node.source_range.begin_pos, node.loc.selector.end_pos)
60
61
  else
61
62
  node.loc.selector
62
63
  end
@@ -66,8 +66,12 @@ module RuboCop
66
66
  MSG = 'Tagging a string as html safe may be a security risk.'
67
67
  RESTRICT_ON_SEND = %i[html_safe raw safe_concat].freeze
68
68
 
69
+ def_node_search :i18n_method?, <<~PATTERN
70
+ (send {nil? (const {nil? cbase} :I18n)} {:t :translate :l :localize} ...)
71
+ PATTERN
72
+
69
73
  def on_send(node)
70
- return if non_interpolated_string?(node)
74
+ return if non_interpolated_string?(node) || i18n_method?(node)
71
75
 
72
76
  return unless looks_like_rails_html_safe?(node) ||
73
77
  looks_like_rails_raw?(node) ||
@@ -43,7 +43,7 @@ module RuboCop
43
43
 
44
44
  def on_block(node)
45
45
  pluck_candidate?(node) do |argument, key|
46
- next unless use_one_block_argument?(argument)
46
+ next if key.regexp_type? || !use_one_block_argument?(argument)
47
47
 
48
48
  match = if node.block_type?
49
49
  block_argument = argument.children.first.source
@@ -51,7 +51,7 @@ module RuboCop
51
51
  private
52
52
 
53
53
  def offense_range(node)
54
- range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
54
+ range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
55
55
  end
56
56
  end
57
57
  end
@@ -93,7 +93,7 @@ module RuboCop
93
93
 
94
94
  def register_offense(node, receiver, other)
95
95
  add_offense(node, message: message(node, receiver, other)) do |corrector|
96
- corrector.replace(node.source_range, replacement(receiver, other, node.left_sibling))
96
+ corrector.replace(node, replacement(receiver, other, node.left_sibling))
97
97
  end
98
98
  end
99
99
 
@@ -128,10 +128,10 @@ module RuboCop
128
128
 
129
129
  if method_call
130
130
  corrector.replace(node.loc.keyword, 'if')
131
- range = method_call.loc.expression
131
+ range = method_call.source_range
132
132
  else
133
133
  variable1, _variable2 = exists_and_not_empty?(node) || not_blank?(node)
134
- range = node.loc.expression
134
+ range = node.source_range
135
135
  end
136
136
 
137
137
  corrector.replace(range, replacement(variable1))
@@ -141,9 +141,9 @@ module RuboCop
141
141
 
142
142
  def unless_condition(node, method_call)
143
143
  if node.modifier_form?
144
- node.loc.keyword.join(node.loc.expression.end)
144
+ node.loc.keyword.join(node.source_range.end)
145
145
  else
146
- node.loc.expression.begin.join(method_call.loc.expression)
146
+ node.source_range.begin.join(method_call.source_range)
147
147
  end
148
148
  end
149
149
 
@@ -48,7 +48,7 @@ module RuboCop
48
48
  task_name = task_method.arguments[0]
49
49
  task_dependency = correct_task_dependency(task_name)
50
50
 
51
- corrector.replace(task_name.loc.expression, task_dependency)
51
+ corrector.replace(task_name, task_dependency)
52
52
  end
53
53
  end
54
54
  end
@@ -52,7 +52,7 @@ module RuboCop
52
52
  return if within_shadowing_method?(node)
53
53
 
54
54
  add_offense(node, message: build_message(node)) do |corrector|
55
- corrector.replace(node.source_range, node_replacement(node))
55
+ corrector.replace(node, node_replacement(node))
56
56
  end
57
57
  end
58
58
 
@@ -62,7 +62,7 @@ module RuboCop
62
62
  elsif prv_sib
63
63
  corrector.remove(range_between(node_end(prv_sib), node_end(allow_nil)))
64
64
  else
65
- corrector.remove(allow_nil.loc.expression)
65
+ corrector.remove(allow_nil)
66
66
  end
67
67
  end
68
68
  end
@@ -87,11 +87,11 @@ module RuboCop
87
87
  end
88
88
 
89
89
  def node_beg(node)
90
- node.loc.expression.begin_pos
90
+ node.source_range.begin_pos
91
91
  end
92
92
 
93
93
  def node_end(node)
94
- node.loc.expression.end_pos
94
+ node.source_range.end_pos
95
95
  end
96
96
  end
97
97
  end
@@ -40,7 +40,7 @@ module RuboCop
40
40
  def on_send(node)
41
41
  association_with_foreign_key(node) do |type, name, options, foreign_key_pair, foreign_key|
42
42
  if redundant?(node, type, name, options, foreign_key)
43
- add_offense(foreign_key_pair.loc.expression) do |corrector|
43
+ add_offense(foreign_key_pair.source_range) do |corrector|
44
44
  range = range_with_surrounding_space(foreign_key_pair.source_range, side: :left)
45
45
  range = range_with_surrounding_comma(range, :left)
46
46
 
@@ -89,7 +89,7 @@ module RuboCop
89
89
  private
90
90
 
91
91
  def autocorrect(corrector, send_node, node)
92
- corrector.remove(send_node.receiver.source_range)
92
+ corrector.remove(send_node.receiver)
93
93
  corrector.remove(send_node.loc.dot)
94
94
  corrector.remove(block_argument_range(send_node)) unless node.numblock_type?
95
95
  end
@@ -18,6 +18,8 @@ module RuboCop
18
18
  # # good
19
19
  # has_many :accounts, class_name: 'Account'
20
20
  class ReflectionClassName < Base
21
+ extend AutoCorrector
22
+
21
23
  MSG = 'Use a string value for `class_name`.'
22
24
  RESTRICT_ON_SEND = %i[has_many has_one belongs_to].freeze
23
25
  ALLOWED_REFLECTION_CLASS_TYPES = %i[dstr str sym].freeze
@@ -32,12 +34,18 @@ module RuboCop
32
34
  (pair (sym :class_name) #reflection_class_value?)
33
35
  PATTERN
34
36
 
37
+ def_node_matcher :const_or_string, <<~PATTERN
38
+ {$(const nil? _) (send $(const nil? _) :name) (send $(const nil? _) :to_s)}
39
+ PATTERN
40
+
35
41
  def on_send(node)
36
42
  association_with_reflection(node) do |reflection_class_name|
37
43
  return if reflection_class_name.value.send_type? && reflection_class_name.value.receiver.nil?
38
44
  return if reflection_class_name.value.lvar_type? && str_assigned?(reflection_class_name)
39
45
 
40
- add_offense(reflection_class_name.loc.expression)
46
+ add_offense(reflection_class_name.source_range) do |corrector|
47
+ autocorrect(corrector, reflection_class_name)
48
+ end
41
49
  end
42
50
  end
43
51
 
@@ -64,6 +72,14 @@ module RuboCop
64
72
  !ALLOWED_REFLECTION_CLASS_TYPES.include?(class_value.type)
65
73
  end
66
74
  end
75
+
76
+ def autocorrect(corrector, class_config)
77
+ class_value = class_config.value
78
+ replacement = const_or_string(class_value)
79
+ return unless replacement.present?
80
+
81
+ corrector.replace(class_value, replacement.source.inspect)
82
+ end
67
83
  end
68
84
  end
69
85
  end
@@ -78,7 +78,7 @@ module RuboCop
78
78
  indent = ' ' * node.loc.column
79
79
  new_code = ["def self.#{const_name.downcase}", "#{indent}#{value.source}", 'end'].join("\n#{indent}")
80
80
 
81
- corrector.replace(node.source_range, new_code)
81
+ corrector.replace(node, new_code)
82
82
  end
83
83
 
84
84
  def message(method_name)
@@ -86,7 +86,7 @@ module RuboCop
86
86
  end
87
87
 
88
88
  def offense_range(name, value)
89
- range_between(name.loc.expression.begin_pos, value.loc.expression.end_pos)
89
+ range_between(name.source_range.begin_pos, value.source_range.end_pos)
90
90
  end
91
91
 
92
92
  def nested_relative_date(node, &callback)
@@ -6,9 +6,9 @@ module RuboCop
6
6
  # Prefer `response.parsed_body` to `JSON.parse(response.body)`.
7
7
  #
8
8
  # @safety
9
- # This cop's autocorrection is unsafe because Content-Type may not be `application/json`. For example, the
10
- # proprietary Content-Type provided by corporate entities such as `application/vnd.github+json` is not
11
- # supported at `response.parsed_body` by default, so you still have to use `JSON.parse(response.body)` there.
9
+ # This cop is unsafe because Content-Type may not be `application/json`. For example, the proprietary
10
+ # Content-Type provided by corporate entities such as `application/vnd.github+json` is not supported at
11
+ # `response.parsed_body` by default, so you still have to use `JSON.parse(response.body)` there.
12
12
  #
13
13
  # @example
14
14
  # # bad
@@ -39,7 +39,7 @@ module RuboCop
39
39
  def on_send(node)
40
40
  evidence(node) do |rails_node, args|
41
41
  add_offense(node, message: format(MSG, root: rails_node.source)) do |corrector|
42
- range = range_between(rails_node.loc.selector.end_pos, node.loc.expression.end_pos)
42
+ range = range_between(rails_node.loc.selector.end_pos, node.source_range.end_pos)
43
43
  replacement = ".join(#{args.map(&:source).join(', ')})"
44
44
 
45
45
  corrector.replace(range, replacement)
@@ -184,7 +184,7 @@ module RuboCop
184
184
  end
185
185
 
186
186
  def build_path_glob_replacement(path, method)
187
- receiver = range_between(path.loc.expression.begin_pos, path.children.first.loc.selector.end_pos).source
187
+ receiver = range_between(path.source_range.begin_pos, path.children.first.loc.selector.end_pos).source
188
188
 
189
189
  argument = path.arguments.one? ? path.first_argument.source : join_arguments(path.arguments)
190
190
 
@@ -73,7 +73,7 @@ module RuboCop
73
73
  method = method_node.source[1..]
74
74
 
75
75
  range = if node.receiver
76
- range_between(node.loc.dot.begin_pos, node.loc.expression.end_pos)
76
+ range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
77
77
  else
78
78
  corrector.insert_before(node, 'self')
79
79
  node
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Enforces that boolean columns are created with default values (`false` or `true`) and
7
+ # `NOT NULL` constraint.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # add_column :users, :active, :boolean
12
+ # t.column :active, :boolean
13
+ # t.boolean :active
14
+ #
15
+ # # good
16
+ # add_column :users, :active, :boolean, default: true, null: false
17
+ # t.column :active, :boolean, default: true, null: false
18
+ # t.boolean :active, default: true, null: false
19
+ #
20
+ class ThreeStateBooleanColumn < Base
21
+ MSG = 'Boolean columns should always have a default value and a `NOT NULL` constraint.'
22
+
23
+ RESTRICT_ON_SEND = %i[add_column column boolean].freeze
24
+
25
+ def_node_matcher :three_state_boolean?, <<~PATTERN
26
+ {
27
+ (send nil? :add_column _ $_ {(sym :boolean) (str "boolean")} $_ ?)
28
+ (send !nil? :column $_ {(sym :boolean) (str "boolean")} $_ ?)
29
+ (send !nil? :boolean $_ $_ ?)
30
+ }
31
+ PATTERN
32
+
33
+ def_node_matcher :required_options?, <<~PATTERN
34
+ (hash <(pair (sym :default) !nil?) (pair (sym :null) false) ...>)
35
+ PATTERN
36
+
37
+ def_node_search :change_column_null?, <<~PATTERN
38
+ (send nil? :change_column_null {(sym %1) (str %1)} {(sym %2) (str %2)} false)
39
+ PATTERN
40
+
41
+ def on_send(node)
42
+ three_state_boolean?(node) do |column_node, options_node|
43
+ options_node = options_node.first
44
+
45
+ return if required_options?(options_node)
46
+
47
+ def_node = node.each_ancestor(:def, :defs).first
48
+ table_node = table_node(node)
49
+ if def_node && (table_node.nil? || change_column_null?(def_node, table_node.value, column_node.value))
50
+ return
51
+ end
52
+
53
+ add_offense(node)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def table_node(node)
60
+ case node.method_name
61
+ when :add_column
62
+ node.first_argument
63
+ when :column, :boolean
64
+ ancestor = node.each_ancestor(:block).find do |n|
65
+ n.method?(:create_table) || n.method?(:change_table)
66
+ end
67
+ ancestor&.send_node&.first_argument
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -70,7 +70,7 @@ module RuboCop
70
70
 
71
71
  def autocorrect(corrector, node)
72
72
  # add `.zone`: `Time.at` => `Time.zone.at`
73
- corrector.insert_after(node.children[0].source_range, '.zone')
73
+ corrector.insert_after(node.children[0], '.zone')
74
74
 
75
75
  case node.method_name
76
76
  when :current
@@ -81,7 +81,7 @@ module RuboCop
81
81
  end
82
82
 
83
83
  # prefer `Time` over `DateTime` class
84
- corrector.replace(node.children.first.source_range, 'Time') if strict?
84
+ corrector.replace(node.children.first, 'Time') if strict?
85
85
  remove_redundant_in_time_zone(corrector, node)
86
86
  end
87
87
 
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Rails
6
6
  # When you define a uniqueness validation in Active Record model,
7
- # you also should add a unique index for the column. There are two reasons
7
+ # you also should add a unique index for the column. There are two reasons.
8
8
  # First, duplicated records may occur even if Active Record's validation
9
9
  # is defined.
10
10
  # Second, it will cause slow queries. The validation executes a `SELECT`
@@ -102,7 +102,7 @@ module RuboCop
102
102
  end
103
103
 
104
104
  def correct_validate_type_for_hash(corrector, node, arguments)
105
- corrector.replace(arguments.loc.expression, "#{validate_type(node)}: #{braced_options(arguments)}")
105
+ corrector.replace(arguments, "#{validate_type(node)}: #{braced_options(arguments)}")
106
106
  end
107
107
 
108
108
  def correct_validate_type_for_array(corrector, node, arguments, loc)
@@ -65,7 +65,7 @@ module RuboCop
65
65
  private
66
66
 
67
67
  def offense_range(node)
68
- range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
68
+ range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
69
69
  end
70
70
 
71
71
  def extract_column_and_value(template_node, value_node)
@@ -105,7 +105,7 @@ module RuboCop
105
105
  if exists_style?
106
106
  node.receiver.loc.selector.join(node.loc.selector)
107
107
  elsif where_style?
108
- node.loc.selector.with(end_pos: node.loc.expression.end_pos)
108
+ node.loc.selector.with(end_pos: node.source_range.end_pos)
109
109
  end
110
110
  end
111
111
 
@@ -43,7 +43,7 @@ module RuboCop
43
43
  next unless root_receiver == root_receiver(where_node)
44
44
  next unless same_relationship?(where_argument, node.first_argument)
45
45
 
46
- range = range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
46
+ range = range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
47
47
  register_offense(node, where_node, where_argument, range)
48
48
  break
49
49
  end
@@ -83,9 +83,9 @@ module RuboCop
83
83
 
84
84
  def replace_range(child)
85
85
  if (right_sibling = child.right_sibling)
86
- range_between(child.loc.expression.begin_pos, right_sibling.loc.expression.begin_pos)
86
+ range_between(child.source_range.begin_pos, right_sibling.source_range.begin_pos)
87
87
  else
88
- range_between(child.left_sibling.loc.expression.end_pos, child.loc.expression.end_pos)
88
+ range_between(child.left_sibling.source_range.end_pos, child.source_range.end_pos)
89
89
  end
90
90
  end
91
91
 
@@ -64,7 +64,7 @@ module RuboCop
64
64
  private
65
65
 
66
66
  def offense_range(node)
67
- range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
67
+ range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
68
68
  end
69
69
 
70
70
  def extract_column_and_value(template_node, value_node)
@@ -32,10 +32,10 @@ module RuboCop
32
32
 
33
33
  def on_send(node)
34
34
  where_not_call?(node) do |args|
35
- next unless args[0].hash_type?
35
+ next unless args[0]&.hash_type?
36
36
  next unless multiple_arguments_hash? args[0]
37
37
 
38
- range = node.receiver.loc.selector.with(end_pos: node.loc.expression.end_pos)
38
+ range = node.receiver.loc.selector.with(end_pos: node.source_range.end_pos)
39
39
 
40
40
  add_offense(range)
41
41
  end
@@ -115,6 +115,7 @@ require_relative 'rails/skips_model_validations'
115
115
  require_relative 'rails/squished_sql_heredocs'
116
116
  require_relative 'rails/strip_heredoc'
117
117
  require_relative 'rails/table_name_assignment'
118
+ require_relative 'rails/three_state_boolean_column'
118
119
  require_relative 'rails/time_zone'
119
120
  require_relative 'rails/time_zone_assignment'
120
121
  require_relative 'rails/to_formatted_s'
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Rails
5
5
  # This module holds the RuboCop Rails version information.
6
6
  module Version
7
- STRING = '2.18.0'
7
+ STRING = '2.19.1'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
data/lib/rubocop-rails.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'rubocop'
4
4
  require 'rack/utils'
5
5
  require 'active_support/inflector'
6
+ require 'active_support/core_ext/object/blank'
6
7
 
7
8
  require_relative 'rubocop/rails'
8
9
  require_relative 'rubocop/rails/version'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.18.0
4
+ version: 2.19.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-02-25 00:00:00.000000000 Z
13
+ date: 2023-04-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -189,6 +189,7 @@ files:
189
189
  - lib/rubocop/cop/rails/squished_sql_heredocs.rb
190
190
  - lib/rubocop/cop/rails/strip_heredoc.rb
191
191
  - lib/rubocop/cop/rails/table_name_assignment.rb
192
+ - lib/rubocop/cop/rails/three_state_boolean_column.rb
192
193
  - lib/rubocop/cop/rails/time_zone.rb
193
194
  - lib/rubocop/cop/rails/time_zone_assignment.rb
194
195
  - lib/rubocop/cop/rails/to_formatted_s.rb
@@ -218,7 +219,7 @@ metadata:
218
219
  homepage_uri: https://docs.rubocop.org/rubocop-rails/
219
220
  changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
220
221
  source_code_uri: https://github.com/rubocop/rubocop-rails/
221
- documentation_uri: https://docs.rubocop.org/rubocop-rails/2.18/
222
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/2.19/
222
223
  bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
223
224
  rubygems_mfa_required: 'true'
224
225
  post_install_message:
@@ -236,7 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
236
237
  - !ruby/object:Gem::Version
237
238
  version: '0'
238
239
  requirements: []
239
- rubygems_version: 3.4.1
240
+ rubygems_version: 3.5.0.dev
240
241
  signing_key:
241
242
  specification_version: 4
242
243
  summary: Automatic Rails code style checking tool.