rubocop-rails 2.5.2 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dec32a9f0b296ef0a59bb3e93086ce5092ef18f49f546643588244503b94c7bc
4
- data.tar.gz: c1f270a92e19d8403896420bb6dfb5b58a389e8042f16513c3efd8aaf6ab0abb
3
+ metadata.gz: b6b55ee8df864d6eaee4a491f4324343ee2274eafcb352952a81ff045832aa22
4
+ data.tar.gz: 344ea324a589dc25ce3e87366c4af33bde4e392acf6acaccf9b9296066680824
5
5
  SHA512:
6
- metadata.gz: 74cfd98f2b2506d2079e034f3e973d07eb3295b247b5dd48ccaebb5bc3461e4ad1c1bc6a2935b3b978203ecbe5cd1db43d616095c0b9a673dfc2222ff2aa79cf
7
- data.tar.gz: 3b48ca258cf1c4910417b2cadcf24244da5ac2d837a730cb584c0096e66b3688e6115ed93d22b619fb6224f84fc23eff250852498c4e6cab5c7f02ac3943fe71
6
+ metadata.gz: 5bdccc2a5e2a45533cb5bb33b2df26872f806dd590c13d640d7449315e56ec6250aebdb876fb37812bb3dd47cdaeda61c6049bc5cf98b01b473a616e9061491b
7
+ data.tar.gz: 6f8673f2e8d0068bcdbe1599936793461bab38f4b333a4ac6e22e03e7162851d6fc20543ec58e3f2fabdf404764b09f8ff47e6a5c23d492f0c8bb28acd012296
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-18 Bozhidar Batsov
1
+ Copyright (c) 2012-20 Bozhidar Batsov
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -78,13 +78,13 @@ Rails/FindBy:
78
78
 
79
79
  ## Documentation
80
80
 
81
- You can read a lot more about RuboCop Rails in its [official docs](https://docs.rubocop.org/projects/rails/).
81
+ You can read a lot more about RuboCop Rails in its [official docs](https://docs.rubocop.org/rubocop-rails/).
82
82
 
83
83
  ## Compatibility
84
84
 
85
85
  Rails cops support the following versions:
86
86
 
87
- - Rails 4.0+
87
+ - Rails 4.2+
88
88
 
89
89
  ## Contributing
90
90
 
@@ -92,7 +92,7 @@ Rails/AssertNot:
92
92
  Rails/BelongsTo:
93
93
  Description: >-
94
94
  Use `optional: true` instead of `required: false` for
95
- `belongs_to` relations'
95
+ `belongs_to` relations.
96
96
  Enabled: true
97
97
  VersionAdded: '0.62'
98
98
 
@@ -119,6 +119,14 @@ Rails/BulkChangeTable:
119
119
  Include:
120
120
  - db/migrate/*.rb
121
121
 
122
+ Rails/ContentTag:
123
+ Description: 'Use `tag` instead of `content_tag`.'
124
+ Reference:
125
+ - 'https://github.com/rails/rails/issues/25195'
126
+ - 'https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag'
127
+ Enabled: true
128
+ VersionAdded: '2.6'
129
+
122
130
  Rails/CreateTableWithTimestamps:
123
131
  Description: >-
124
132
  Checks the migration for which timestamps are not included
@@ -165,8 +173,14 @@ Rails/DynamicFindBy:
165
173
  StyleGuide: 'https://rails.rubystyle.guide#find_by'
166
174
  Enabled: true
167
175
  VersionAdded: '0.44'
176
+ VersionChanged: '2.6'
177
+ # The `Whitelist` has been deprecated, Please use `AllowedMethods` instead.
168
178
  Whitelist:
169
179
  - find_by_sql
180
+ AllowedMethods:
181
+ - find_by_sql
182
+ AllowedReceivers:
183
+ - Gem::Specification
170
184
 
171
185
  Rails/EnumHash:
172
186
  Description: 'Prefer hash syntax over array syntax when defining enums.'
@@ -184,7 +198,7 @@ Rails/EnumUniqueness:
184
198
  - app/models/**/*.rb
185
199
 
186
200
  Rails/EnvironmentComparison:
187
- Description: "Favor `Rails.env.production?` over `Rails.env == 'production'`"
201
+ Description: "Favor `Rails.env.production?` over `Rails.env == 'production'`."
188
202
  Enabled: true
189
203
  VersionAdded: '0.52'
190
204
 
@@ -245,7 +259,7 @@ Rails/HasManyOrHasOneDependent:
245
259
  - app/models/**/*.rb
246
260
 
247
261
  Rails/HelperInstanceVariable:
248
- Description: 'Do not use instance variables in helpers'
262
+ Description: 'Do not use instance variables in helpers.'
249
263
  Enabled: true
250
264
  VersionAdded: '2.0'
251
265
  Include:
@@ -312,7 +326,7 @@ Rails/LinkToBlank:
312
326
  VersionAdded: '0.62'
313
327
 
314
328
  Rails/NotNullColumn:
315
- Description: 'Do not add a NOT NULL column without a default value'
329
+ Description: 'Do not add a NOT NULL column without a default value.'
316
330
  Enabled: true
317
331
  VersionAdded: '0.43'
318
332
  Include:
@@ -334,6 +348,12 @@ Rails/OutputSafety:
334
348
  Enabled: true
335
349
  VersionAdded: '0.41'
336
350
 
351
+ Rails/Pick:
352
+ Description: 'Prefer `pick` over `pluck(...).first`.'
353
+ Enabled: true
354
+ Safe: false
355
+ VersionAdded: '2.6'
356
+
337
357
  Rails/PluralizationGrammar:
338
358
  Description: 'Checks for incorrect grammar when using methods like `3.day.ago`.'
339
359
  Enabled: true
@@ -361,6 +381,7 @@ Rails/RakeEnvironment:
361
381
  Enabled: true
362
382
  Safe: false
363
383
  VersionAdded: '2.4'
384
+ VersionChanged: '2.6'
364
385
  Include:
365
386
  - '**/Rakefile'
366
387
  - '**/*.rake'
@@ -387,6 +408,11 @@ Rails/RedundantAllowNil:
387
408
  Include:
388
409
  - app/models/**/*.rb
389
410
 
411
+ Rails/RedundantForeignKey:
412
+ Description: 'Checks for associations where the `:foreign_key` option is redundant.'
413
+ Enabled: true
414
+ VersionAdded: '2.6'
415
+
390
416
  Rails/RedundantReceiverInWithOptions:
391
417
  Description: 'Checks for redundant receiver in `with_options`.'
392
418
  Enabled: true
@@ -434,7 +460,7 @@ Rails/ReversibleMigration:
434
460
  - db/migrate/*.rb
435
461
 
436
462
  Rails/SafeNavigation:
437
- Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`"
463
+ Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`."
438
464
  Enabled: true
439
465
  VersionAdded: '0.43'
440
466
  # This will convert usages of `try` to use safe navigation as well as `try!`.
@@ -513,7 +539,7 @@ Rails/UniqBeforePluck:
513
539
  Description: 'Prefer the use of uniq or distinct before pluck.'
514
540
  Enabled: true
515
541
  VersionAdded: '0.40'
516
- VersionChanged: '0.47'
542
+ VersionChanged: '2.6'
517
543
  EnforcedStyle: conservative
518
544
  SupportedStyles:
519
545
  - conservative
@@ -543,3 +569,7 @@ Rails/Validation:
543
569
  VersionChanged: '0.41'
544
570
  Include:
545
571
  - app/models/**/*.rb
572
+
573
+ # Accept `redirect_to(...) and return` and similar cases.
574
+ Style/AndOr:
575
+ EnforcedStyle: conditionals
@@ -15,9 +15,7 @@ module RuboCop
15
15
  PATTERN
16
16
 
17
17
  def external_dependency_checksum
18
- if defined?(@external_dependency_checksum)
19
- return @external_dependency_checksum
20
- end
18
+ return @external_dependency_checksum if defined?(@external_dependency_checksum)
21
19
 
22
20
  schema_path = RuboCop::Rails::SchemaLoader.db_schema_path
23
21
  return nil if schema_path.nil?
@@ -112,7 +112,14 @@ module RuboCop
112
112
  end
113
113
 
114
114
  def self.from_map_to_h(node, match)
115
- strip_trailing_chars = node.parent&.block_type? ? 0 : '.to_h'.length
115
+ strip_trailing_chars = 0
116
+
117
+ unless node.parent&.block_type?
118
+ map_range = node.children.first.source_range
119
+ node_range = node.source_range
120
+ strip_trailing_chars = node_range.end_pos - map_range.end_pos
121
+ end
122
+
116
123
  new(match, node.children.first, 0, strip_trailing_chars)
117
124
  end
118
125
 
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks that `tag` is used instead of `content_tag`
7
+ # because `content_tag` is legacy syntax.
8
+ #
9
+ # NOTE: Allow `content_tag` when the first argument is a variable because
10
+ # `content_tag(name)` is simpler rather than `tag.public_send(name)`.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # content_tag(:p, 'Hello world!')
15
+ # content_tag(:br)
16
+ #
17
+ # # good
18
+ # tag.p('Hello world!')
19
+ # tag.br
20
+ # content_tag(name, 'Hello world!')
21
+ class ContentTag < Cop
22
+ include RangeHelp
23
+ extend TargetRailsVersion
24
+
25
+ minimum_target_rails_version 5.1
26
+
27
+ MSG = 'Use `tag` instead of `content_tag`.'
28
+
29
+ def on_send(node)
30
+ return unless node.method?(:content_tag)
31
+
32
+ first_argument = node.first_argument
33
+ return unless first_argument
34
+
35
+ return if first_argument.variable? || first_argument.send_type? || first_argument.const_type?
36
+
37
+ add_offense(node)
38
+ end
39
+
40
+ def autocorrect(node)
41
+ lambda do |corrector|
42
+ if method_name?(node.first_argument)
43
+ replace_method_with_tag_method(corrector, node)
44
+ remove_first_argument(corrector, node)
45
+ else
46
+ corrector.replace(node.loc.selector, 'tag')
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def method_name?(node)
54
+ return false unless node.str_type? || node.sym_type?
55
+
56
+ /^[a-zA-Z_][a-zA-Z_0-9]*$/.match?(node.value)
57
+ end
58
+
59
+ def replace_method_with_tag_method(corrector, node)
60
+ corrector.replace(
61
+ node.loc.selector,
62
+ "tag.#{node.first_argument.value}"
63
+ )
64
+ end
65
+
66
+ def remove_first_argument(corrector, node)
67
+ if node.arguments.length > 1
68
+ corrector.remove(
69
+ range_between(child_node_beg(node, 0), child_node_beg(node, 1))
70
+ )
71
+ elsif node.arguments.length == 1
72
+ corrector.remove(node.arguments[0].loc.expression)
73
+ end
74
+ end
75
+
76
+ def child_node_beg(node, index)
77
+ node.arguments[index].loc.expression.begin_pos
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -70,9 +70,7 @@ module RuboCop
70
70
  parent = node.parent
71
71
 
72
72
  if create_table_with_block?(parent)
73
- if parent.body.nil? || !time_columns_included?(parent.body)
74
- add_offense(parent)
75
- end
73
+ add_offense(parent) if parent.body.nil? || !time_columns_included?(parent.body)
76
74
  elsif create_table_with_timestamps_proc?(node)
77
75
  # nothing to do
78
76
  else
@@ -71,9 +71,7 @@ module RuboCop
71
71
  delegation = ["delegate :#{node.body.method_name}",
72
72
  "to: :#{node.body.receiver.method_name}"]
73
73
 
74
- if node.method?(prefixed_method_name(node.body))
75
- delegation << ['prefix: true']
76
- end
74
+ delegation << ['prefix: true'] if node.method?(prefixed_method_name(node.body))
77
75
 
78
76
  lambda do |corrector|
79
77
  corrector.replace(node.source_range, delegation.join(', '))
@@ -10,37 +10,41 @@ module RuboCop
10
10
  # @example
11
11
  # # bad
12
12
  # User.find_by_name(name)
13
- #
14
- # # bad
15
13
  # User.find_by_name_and_email(name)
16
- #
17
- # # bad
18
14
  # User.find_by_email!(name)
19
15
  #
20
16
  # # good
21
17
  # User.find_by(name: name)
18
+ # User.find_by(name: name, email: email)
19
+ # User.find_by!(email: email)
20
+ #
21
+ # @example AllowedMethods: find_by_sql
22
+ # # bad
23
+ # User.find_by_query(users_query)
22
24
  #
23
25
  # # good
24
- # User.find_by(name: name, email: email)
26
+ # User.find_by_sql(users_sql)
27
+ #
28
+ # @example AllowedReceivers: Gem::Specification
29
+ # # bad
30
+ # Specification.find_by_name('backend').gem_dir
25
31
  #
26
32
  # # good
27
- # User.find_by!(email: email)
33
+ # Gem::Specification.find_by_name('backend').gem_dir
28
34
  class DynamicFindBy < Cop
29
35
  MSG = 'Use `%<static_name>s` instead of dynamic `%<method>s`.'
30
36
  METHOD_PATTERN = /^find_by_(.+?)(!)?$/.freeze
31
37
 
32
38
  def on_send(node)
33
- method_name = node.method_name.to_s
34
-
35
- return if whitelist.include?(method_name)
39
+ return if allowed_invocation?(node)
36
40
 
41
+ method_name = node.method_name
37
42
  static_name = static_method_name(method_name)
38
-
39
43
  return unless static_name
40
44
 
41
45
  add_offense(node,
42
46
  message: format(MSG, static_name: static_name,
43
- method: node.method_name))
47
+ method: method_name))
44
48
  end
45
49
  alias on_csend on_send
46
50
 
@@ -57,6 +61,31 @@ module RuboCop
57
61
 
58
62
  private
59
63
 
64
+ def allowed_invocation?(node)
65
+ allowed_method?(node) || allowed_receiver?(node) ||
66
+ whitelisted?(node)
67
+ end
68
+
69
+ def allowed_method?(node)
70
+ return unless cop_config['AllowedMethods']
71
+
72
+ cop_config['AllowedMethods'].include?(node.method_name.to_s)
73
+ end
74
+
75
+ def allowed_receiver?(node)
76
+ return unless cop_config['AllowedReceivers'] && node.receiver
77
+
78
+ cop_config['AllowedReceivers'].include?(node.receiver.source)
79
+ end
80
+
81
+ # config option `WhiteList` will be deprecated soon
82
+ def whitelisted?(node)
83
+ whitelist_config = cop_config['Whitelist']
84
+ return unless whitelist_config
85
+
86
+ whitelist_config.include?(node.method_name.to_s)
87
+ end
88
+
60
89
  def autocorrect_method_name(corrector, node)
61
90
  corrector.replace(node.loc.selector,
62
91
  static_method_name(node.method_name.to_s))
@@ -68,10 +97,6 @@ module RuboCop
68
97
  end
69
98
  end
70
99
 
71
- def whitelist
72
- cop_config['Whitelist']
73
- end
74
-
75
100
  def column_keywords(method)
76
101
  keyword_string = method.to_s[METHOD_PATTERN, 1]
77
102
  keyword_string.split('_and_').map { |keyword| "#{keyword}: " }
@@ -9,11 +9,11 @@ module RuboCop
9
9
  #
10
10
  # There are two obvious cases where `exit` is particularly harmful:
11
11
  #
12
- # - Usage in library code for your application. Even though Rails will
12
+ # * Usage in library code for your application. Even though Rails will
13
13
  # rescue from a `SystemExit` and continue on, unit testing that library
14
14
  # code will result in specs exiting (potentially silently if `exit(0)`
15
15
  # is used.)
16
- # - Usage in application code outside of the web process could result in
16
+ # * Usage in application code outside of the web process could result in
17
17
  # the program exiting, which could result in the code failing to run and
18
18
  # do its job.
19
19
  #
@@ -48,6 +48,7 @@ module RuboCop
48
48
 
49
49
  def on_dstr(node)
50
50
  return unless rails_root_nodes?(node)
51
+ return unless node.children.last.str_type?
51
52
  return unless node.children.last.source.start_with?('.') ||
52
53
  node.children.last.source.include?(File::SEPARATOR)
53
54
 
@@ -8,7 +8,7 @@ module RuboCop
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
- # .rubocop.yml file to 4.0, etc.
11
+ # .rubocop.yml file to 4.2.
12
12
  #
13
13
  # @example
14
14
  # # bad
@@ -83,6 +83,7 @@ module RuboCop
83
83
  'to define HTTP status code.'
84
84
 
85
85
  attr_reader :node
86
+
86
87
  def initialize(node)
87
88
  @node = node
88
89
  end
@@ -124,6 +125,7 @@ module RuboCop
124
125
  PERMITTED_STATUS = %i[error success missing redirect].freeze
125
126
 
126
127
  attr_reader :node
128
+
127
129
  def initialize(node)
128
130
  @node = node
129
131
  end
@@ -129,10 +129,6 @@ module RuboCop
129
129
  # @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
130
130
  # @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
131
131
  class InverseOf < Cop
132
- extend TargetRailsVersion
133
-
134
- minimum_target_rails_version 4.1
135
-
136
132
  SPECIFY_MSG = 'Specify an `:inverse_of` option.'
137
133
  NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to ' \
138
134
  'use `inverse_of: false`.'
@@ -42,9 +42,7 @@ module RuboCop
42
42
 
43
43
  option_nodes.map(&:children).each do |options|
44
44
  blank = options.find { |o| blank_target?(o) }
45
- if blank && options.none? { |o| includes_noopener?(o) }
46
- add_offense(blank)
47
- end
45
+ add_offense(blank) if blank && options.none? { |o| includes_noopener?(o) }
48
46
  end
49
47
  end
50
48
 
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop enforces the use `pick` over `pluck(...).first`.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # Model.pluck(:a).first
11
+ # Model.pluck(:a, :b).first
12
+ #
13
+ # # good
14
+ # Model.pick(:a)
15
+ # Model.pick(:a, :b)
16
+ class Pick < Cop
17
+ extend TargetRailsVersion
18
+
19
+ MSG = 'Prefer `pick(%<args>s)` over `pluck(%<args>s).first`.'
20
+
21
+ minimum_target_rails_version 6.0
22
+
23
+ def_node_matcher :pick_candidate?, <<~PATTERN
24
+ (send (send _ :pluck ...) :first)
25
+ PATTERN
26
+
27
+ def on_send(node)
28
+ pick_candidate?(node) do
29
+ range = node.receiver.loc.selector.join(node.loc.selector)
30
+ add_offense(node, location: range)
31
+ end
32
+ end
33
+
34
+ def autocorrect(node)
35
+ first_range = node.receiver.source_range.end.join(node.loc.selector)
36
+
37
+ lambda do |corrector|
38
+ corrector.remove(first_range)
39
+ corrector.replace(node.receiver.loc.selector, 'pick')
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def message(node)
46
+ format(MSG, args: node.receiver.arguments.map(&:source).join(', '))
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -76,15 +76,11 @@ module RuboCop
76
76
  return if ignore_if_node?(node)
77
77
 
78
78
  redundant_receiver_and_other(node) do |receiver, other|
79
- unless ignore_other_node?(other) || receiver.nil?
80
- add_offense(node, message: message(node, receiver, other))
81
- end
79
+ add_offense(node, message: message(node, receiver, other)) unless ignore_other_node?(other) || receiver.nil?
82
80
  end
83
81
 
84
82
  redundant_negative_receiver_and_other(node) do |receiver, other|
85
- unless ignore_other_node?(other) || receiver.nil?
86
- add_offense(node, message: message(node, receiver, other))
87
- end
83
+ add_offense(node, message: message(node, receiver, other)) unless ignore_other_node?(other) || receiver.nil?
88
84
  end
89
85
  end
90
86
 
@@ -41,8 +41,25 @@ module RuboCop
41
41
  end
42
42
  end
43
43
 
44
+ def autocorrect(node)
45
+ lambda do |corrector|
46
+ task_name = node.arguments[0]
47
+ task_dependency = correct_task_dependency(task_name)
48
+
49
+ corrector.replace(task_name.loc.expression, task_dependency)
50
+ end
51
+ end
52
+
44
53
  private
45
54
 
55
+ def correct_task_dependency(task_name)
56
+ if task_name.sym_type?
57
+ task_name.source.delete(':|\'|"') + ': :environment'
58
+ else
59
+ "#{task_name.source} => :environment"
60
+ end
61
+ end
62
+
46
63
  def task_name(node)
47
64
  first_arg = node.arguments[0]
48
65
  case first_arg&.type
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop detects cases where the `:foreign_key` option on associations
7
+ # is redundant.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # class Post
12
+ # has_many :comments, foreign_key: 'post_id'
13
+ # end
14
+ #
15
+ # class Comment
16
+ # belongs_to :post, foreign_key: 'post_id'
17
+ # end
18
+ #
19
+ # # good
20
+ # class Post
21
+ # has_many :comments
22
+ # end
23
+ #
24
+ # class Comment
25
+ # belongs_to :author, foreign_key: 'user_id'
26
+ # end
27
+ class RedundantForeignKey < Cop
28
+ include RangeHelp
29
+
30
+ MSG = 'Specifying the default value for `foreign_key` is redundant.'
31
+
32
+ def_node_matcher :association_with_foreign_key, <<~PATTERN
33
+ (send nil? ${:belongs_to :has_one :has_many :has_and_belongs_to_many} ({sym str} $_)
34
+ $(hash <$(pair (sym :foreign_key) ({sym str} $_)) ...>)
35
+ )
36
+ PATTERN
37
+
38
+ def on_send(node)
39
+ association_with_foreign_key(node) do |type, name, options, foreign_key_pair, foreign_key|
40
+ if redundant?(node, type, name, options, foreign_key)
41
+ add_offense(node, location: foreign_key_pair.loc.expression)
42
+ end
43
+ end
44
+ end
45
+
46
+ def autocorrect(node)
47
+ _type, _name, _options, foreign_key_pair, _foreign_key = association_with_foreign_key(node)
48
+ range = range_with_surrounding_space(range: foreign_key_pair.source_range, side: :left)
49
+ range = range_with_surrounding_comma(range, :left)
50
+
51
+ lambda do |corrector|
52
+ corrector.remove(range)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def redundant?(node, association_type, association_name, options, foreign_key)
59
+ foreign_key.to_s == default_foreign_key(node, association_type, association_name, options)
60
+ end
61
+
62
+ def default_foreign_key(node, association_type, association_name, options)
63
+ if association_type == :belongs_to
64
+ "#{association_name}_id"
65
+ elsif (as = find_as_option(options))
66
+ "#{as}_id"
67
+ else
68
+ node.parent_module_name&.foreign_key
69
+ end
70
+ end
71
+
72
+ def find_as_option(options)
73
+ options.pairs.find do |pair|
74
+ pair.key.sym_type? && pair.key.value == :as
75
+ end&.value&.value
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -55,11 +55,8 @@ module RuboCop
55
55
  # end
56
56
  # end
57
57
  class RedundantReceiverInWithOptions < Cop
58
- extend TargetRailsVersion
59
58
  include RangeHelp
60
59
 
61
- minimum_target_rails_version 4.2
62
-
63
60
  MSG = 'Redundant receiver in `with_options`.'
64
61
 
65
62
  def_node_matcher :with_options?, <<~PATTERN
@@ -9,14 +9,14 @@ module RuboCop
9
9
  #
10
10
  # This will allow:
11
11
  #
12
- # - update or save calls, assigned to a variable,
12
+ # * update or save calls, assigned to a variable,
13
13
  # or used as a condition in an if/unless/case statement.
14
- # - create calls, assigned to a variable that then has a
14
+ # * create calls, assigned to a variable that then has a
15
15
  # call to `persisted?`, or whose return value is checked by
16
16
  # `persisted?` immediately
17
- # - calls if the result is explicitly returned from methods and blocks,
17
+ # * calls if the result is explicitly returned from methods and blocks,
18
18
  # or provided as arguments.
19
- # - calls whose signature doesn't look like an ActiveRecord
19
+ # * calls whose signature doesn't look like an ActiveRecord
20
20
  # persistence method.
21
21
  #
22
22
  # By default it will also allow implicit returns from methods and blocks.
@@ -218,9 +218,7 @@ module RuboCop
218
218
  def check_used_in_condition_or_compound_boolean(node)
219
219
  return false unless in_condition_or_compound_boolean?(node)
220
220
 
221
- unless MODIFY_PERSIST_METHODS.include?(node.method_name)
222
- add_offense_for_node(node, CREATE_CONDITIONAL_MSG)
223
- end
221
+ add_offense_for_node(node, CREATE_CONDITIONAL_MSG) unless MODIFY_PERSIST_METHODS.include?(node.method_name)
224
222
 
225
223
  true
226
224
  end
@@ -248,6 +246,7 @@ module RuboCop
248
246
 
249
247
  def allowed_receiver?(node)
250
248
  return false unless node.receiver
249
+ return true if node.receiver.const_name == 'ENV'
251
250
  return false unless cop_config['AllowedReceivers']
252
251
 
253
252
  cop_config['AllowedReceivers'].any? do |allowed_receiver|
@@ -50,7 +50,10 @@ module RuboCop
50
50
  update_counters].freeze
51
51
 
52
52
  def_node_matcher :good_touch?, <<~PATTERN
53
- (send (const nil? :FileUtils) :touch ...)
53
+ {
54
+ (send (const nil? :FileUtils) :touch ...)
55
+ (send _ :touch {true false})
56
+ }
54
57
  PATTERN
55
58
 
56
59
  def on_send(node)
@@ -85,9 +85,7 @@ module RuboCop
85
85
  end
86
86
 
87
87
  # prefer `Time` over `DateTime` class
88
- if strict?
89
- corrector.replace(node.children.first.source_range, 'Time')
90
- end
88
+ corrector.replace(node.children.first.source_range, 'Time') if strict?
91
89
  remove_redundant_in_time_zone(corrector, node)
92
90
  end
93
91
  end
@@ -3,50 +3,51 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # Prefer the use of uniq (or distinct), before pluck instead of after.
6
+ # Prefer the use of distinct, before pluck instead of after.
7
7
  #
8
- # The use of uniq before pluck is preferred because it executes within
8
+ # The use of distinct before pluck is preferred because it executes within
9
9
  # the database.
10
10
  #
11
11
  # This cop has two different enforcement modes. When the EnforcedStyle
12
12
  # is conservative (the default) then only calls to pluck on a constant
13
- # (i.e. a model class) before uniq are added as offenses.
13
+ # (i.e. a model class) before distinct are added as offenses.
14
14
  #
15
15
  # When the EnforcedStyle is aggressive then all calls to pluck before
16
- # uniq are added as offenses. This may lead to false positives as the cop
17
- # cannot distinguish between calls to pluck on an ActiveRecord::Relation
18
- # vs a call to pluck on an ActiveRecord::Associations::CollectionProxy.
16
+ # distinct are added as offenses. This may lead to false positives
17
+ # as the cop cannot distinguish between calls to pluck on an
18
+ # ActiveRecord::Relation vs a call to pluck on an
19
+ # ActiveRecord::Associations::CollectionProxy.
19
20
  #
20
21
  # Autocorrect is disabled by default for this cop since it may generate
21
22
  # false positives.
22
23
  #
23
24
  # @example EnforcedStyle: conservative (default)
24
25
  # # bad
25
- # Model.pluck(:id).uniq
26
+ # Model.pluck(:id).distinct
26
27
  #
27
28
  # # good
28
- # Model.uniq.pluck(:id)
29
+ # Model.distinct.pluck(:id)
29
30
  #
30
31
  # @example EnforcedStyle: aggressive
31
32
  # # bad
32
33
  # # this will return a Relation that pluck is called on
33
- # Model.where(cond: true).pluck(:id).uniq
34
+ # Model.where(cond: true).pluck(:id).distinct
34
35
  #
35
36
  # # bad
36
37
  # # an association on an instance will return a CollectionProxy
37
- # instance.assoc.pluck(:id).uniq
38
+ # instance.assoc.pluck(:id).distinct
38
39
  #
39
40
  # # bad
40
- # Model.pluck(:id).uniq
41
+ # Model.pluck(:id).distinct
41
42
  #
42
43
  # # good
43
- # Model.uniq.pluck(:id)
44
+ # Model.distinct.pluck(:id)
44
45
  #
45
46
  class UniqBeforePluck < RuboCop::Cop::Cop
46
47
  include ConfigurableEnforcedStyle
47
48
  include RangeHelp
48
49
 
49
- MSG = 'Use `%<method>s` before `pluck`.'
50
+ MSG = 'Use `distinct` before `pluck`.'
50
51
  NEWLINE = "\n"
51
52
  PATTERN = '[!^block (send (send %<type>s :pluck ...) ' \
52
53
  '${:uniq :distinct} ...)]'
@@ -66,8 +67,7 @@ module RuboCop
66
67
 
67
68
  return unless method
68
69
 
69
- add_offense(node, location: :selector,
70
- message: format(MSG, method: method))
70
+ add_offense(node, location: :selector)
71
71
  end
72
72
 
73
73
  def autocorrect(node)
@@ -75,7 +75,7 @@ module RuboCop
75
75
  method = node.method_name
76
76
 
77
77
  corrector.remove(dot_method_with_whitespace(method, node))
78
- corrector.insert_before(node.receiver.loc.dot.begin, ".#{method}")
78
+ corrector.insert_before(node.receiver.loc.dot.begin, '.distinct')
79
79
  end
80
80
  end
81
81
 
@@ -15,8 +15,6 @@ module RuboCop
15
15
  # Rails.env.production?
16
16
  # Rails.env == 'production'
17
17
  class UnknownEnv < Cop
18
- include NameSimilarity
19
-
20
18
  MSG = 'Unknown environment `%<name>s`.'
21
19
  MSG_SIMILAR = 'Unknown environment `%<name>s`. ' \
22
20
  'Did you mean `%<similar>s`?'
@@ -57,11 +55,14 @@ module RuboCop
57
55
 
58
56
  def message(name)
59
57
  name = name.to_s.chomp('?')
60
- similar = find_similar_name(name, [])
61
- if similar
62
- format(MSG_SIMILAR, name: name, similar: similar)
63
- else
58
+
59
+ spell_checker = DidYouMean::SpellChecker.new(dictionary: environments)
60
+ similar_names = spell_checker.correct(name)
61
+
62
+ if similar_names.empty?
64
63
  format(MSG, name: name)
64
+ else
65
+ format(MSG_SIMILAR, name: name, similar: similar_names.join(', '))
65
66
  end
66
67
  end
67
68
 
@@ -16,6 +16,7 @@ require_relative 'rails/assert_not'
16
16
  require_relative 'rails/belongs_to'
17
17
  require_relative 'rails/blank'
18
18
  require_relative 'rails/bulk_change_table'
19
+ require_relative 'rails/content_tag'
19
20
  require_relative 'rails/create_table_with_timestamps'
20
21
  require_relative 'rails/date'
21
22
  require_relative 'rails/delegate'
@@ -42,12 +43,14 @@ require_relative 'rails/link_to_blank'
42
43
  require_relative 'rails/not_null_column'
43
44
  require_relative 'rails/output'
44
45
  require_relative 'rails/output_safety'
46
+ require_relative 'rails/pick'
45
47
  require_relative 'rails/pluralization_grammar'
46
48
  require_relative 'rails/presence'
47
49
  require_relative 'rails/present'
48
50
  require_relative 'rails/rake_environment'
49
51
  require_relative 'rails/read_write_attribute'
50
52
  require_relative 'rails/redundant_allow_nil'
53
+ require_relative 'rails/redundant_foreign_key'
51
54
  require_relative 'rails/redundant_receiver_in_with_options'
52
55
  require_relative 'rails/reflection_class_name'
53
56
  require_relative 'rails/refute_methods'
@@ -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.5.2'
7
+ STRING = '2.6.0'
8
8
  end
9
9
  end
10
10
  end
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.5.2
4
+ version: 2.6.0
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: 2020-04-09 00:00:00.000000000 Z
13
+ date: 2020-06-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: 4.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '0'
28
+ version: 4.2.0
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: rack
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -46,14 +46,14 @@ dependencies:
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 0.72.0
49
+ version: 0.82.0
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: 0.72.0
56
+ version: 0.82.0
57
57
  description: |
58
58
  Automatic Rails code style checking tool.
59
59
  A RuboCop extension focused on enforcing Rails best practices and coding conventions.
@@ -84,6 +84,7 @@ files:
84
84
  - lib/rubocop/cop/rails/belongs_to.rb
85
85
  - lib/rubocop/cop/rails/blank.rb
86
86
  - lib/rubocop/cop/rails/bulk_change_table.rb
87
+ - lib/rubocop/cop/rails/content_tag.rb
87
88
  - lib/rubocop/cop/rails/create_table_with_timestamps.rb
88
89
  - lib/rubocop/cop/rails/date.rb
89
90
  - lib/rubocop/cop/rails/delegate.rb
@@ -110,12 +111,14 @@ files:
110
111
  - lib/rubocop/cop/rails/not_null_column.rb
111
112
  - lib/rubocop/cop/rails/output.rb
112
113
  - lib/rubocop/cop/rails/output_safety.rb
114
+ - lib/rubocop/cop/rails/pick.rb
113
115
  - lib/rubocop/cop/rails/pluralization_grammar.rb
114
116
  - lib/rubocop/cop/rails/presence.rb
115
117
  - lib/rubocop/cop/rails/present.rb
116
118
  - lib/rubocop/cop/rails/rake_environment.rb
117
119
  - lib/rubocop/cop/rails/read_write_attribute.rb
118
120
  - lib/rubocop/cop/rails/redundant_allow_nil.rb
121
+ - lib/rubocop/cop/rails/redundant_foreign_key.rb
119
122
  - lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb
120
123
  - lib/rubocop/cop/rails/reflection_class_name.rb
121
124
  - lib/rubocop/cop/rails/refute_methods.rb
@@ -142,10 +145,10 @@ homepage: https://github.com/rubocop-hq/rubocop-rails
142
145
  licenses:
143
146
  - MIT
144
147
  metadata:
145
- homepage_uri: https://docs.rubocop.org/projects/rails/
148
+ homepage_uri: https://docs.rubocop.org/rubocop-rails/
146
149
  changelog_uri: https://github.com/rubocop-hq/rubocop-rails/blob/master/CHANGELOG.md
147
150
  source_code_uri: https://github.com/rubocop-hq/rubocop-rails/
148
- documentation_uri: https://docs.rubocop.org/projects/rails/
151
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/
149
152
  bug_tracker_uri: https://github.com/rubocop-hq/rubocop-rails/issues
150
153
  post_install_message:
151
154
  rdoc_options: []
@@ -155,14 +158,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
155
158
  requirements:
156
159
  - - ">="
157
160
  - !ruby/object:Gem::Version
158
- version: 2.3.0
161
+ version: 2.4.0
159
162
  required_rubygems_version: !ruby/object:Gem::Requirement
160
163
  requirements:
161
164
  - - ">="
162
165
  - !ruby/object:Gem::Version
163
166
  version: '0'
164
167
  requirements: []
165
- rubygems_version: 3.1.2
168
+ rubygems_version: 3.1.3
166
169
  signing_key:
167
170
  specification_version: 4
168
171
  summary: Automatic Rails code style checking tool.