rubocop-rails 2.5.2 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
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.