rubocop-rails 2.9.1 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +68 -4
  5. data/config/obsoletion.yml +7 -0
  6. data/lib/rubocop/cop/mixin/active_record_helper.rb +11 -0
  7. data/lib/rubocop/cop/rails/attribute_default_block_value.rb +1 -1
  8. data/lib/rubocop/cop/rails/belongs_to.rb +1 -1
  9. data/lib/rubocop/cop/rails/blank.rb +4 -0
  10. data/lib/rubocop/cop/rails/content_tag.rb +18 -3
  11. data/lib/rubocop/cop/rails/dynamic_find_by.rb +2 -1
  12. data/lib/rubocop/cop/rails/environment_variable_access.rb +67 -0
  13. data/lib/rubocop/cop/rails/file_path.rb +2 -4
  14. data/lib/rubocop/cop/rails/find_each.rb +2 -0
  15. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +34 -4
  16. data/lib/rubocop/cop/rails/http_positional_arguments.rb +8 -1
  17. data/lib/rubocop/cop/rails/link_to_blank.rb +5 -1
  18. data/lib/rubocop/cop/rails/reflection_class_name.rb +14 -1
  19. data/lib/rubocop/cop/rails/relative_date_constant.rb +16 -15
  20. data/lib/rubocop/cop/rails/require_dependency.rb +38 -0
  21. data/lib/rubocop/cop/rails/reversible_migration.rb +1 -1
  22. data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
  23. data/lib/rubocop/cop/rails/safe_navigation.rb +20 -2
  24. data/lib/rubocop/cop/rails/time_zone.rb +13 -5
  25. data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
  26. data/lib/rubocop/cop/rails/unknown_env.rb +1 -1
  27. data/lib/rubocop/cop/rails/where_exists.rb +11 -0
  28. data/lib/rubocop/cop/rails/where_not.rb +5 -1
  29. data/lib/rubocop/cop/rails_cops.rb +4 -0
  30. data/lib/rubocop/rails.rb +2 -0
  31. data/lib/rubocop/rails/schema_loader/schema.rb +1 -3
  32. data/lib/rubocop/rails/version.rb +1 -1
  33. metadata +16 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a4f37840f94de73bdcc15533ef3e5e95ee265a79fd0486b5e813ee926421d17
4
- data.tar.gz: b2fee8ee1727d8cf33c1d0568f12378f1115d1ae00aa52295656d232de8c59af
3
+ metadata.gz: 8acb3cfc05c02eae959355280c244243a1dd2f6a979c3468e505015844144c97
4
+ data.tar.gz: 0ba96204c723ae8ec4e7e3ca1b17760b9a8dcc7dfce9b9bc13c008243d35e672
5
5
  SHA512:
6
- metadata.gz: d4ceba3963546eaa994918f85d1558223de162f66de58ac48d1e466c2b126facf7548053c00fcbfcd4d05e2d1225eed32e15e6ff921627cfb2a14014119df757
7
- data.tar.gz: af84d0f778766239432a0b599e21c0e6671b02739769570b2c8655df5f32770f796978747d02a321a5ad1ea2c009d60b7ec3e93b09f669106ad9305a4cc50c3e
6
+ metadata.gz: 866bd70db471cfbc203226e0007e660c82f2914dcfcf43c3385d9063599935812783525132785b1256abad61b46c960a372dca0d38d64acf22b63a7eb8b76819
7
+ data.tar.gz: aa456d390b46dad8be62e104d293e1fdbb4fc1d13c3a68affd1238c29773509e55ded7dd4b219734c4d51d0099d8d44894df145690013c0712d80089d51c9fe7
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-20 Bozhidar Batsov
1
+ Copyright (c) 2012-21 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
@@ -1,9 +1,9 @@
1
1
  # RuboCop Rails
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rubocop-rails.svg)](https://badge.fury.io/rb/rubocop-rails)
4
- [![CircleCI](https://circleci.com/gh/rubocop-hq/rubocop-rails.svg?style=svg)](https://circleci.com/gh/rubocop-hq/rubocop-rails)
4
+ [![CircleCI](https://circleci.com/gh/rubocop/rubocop-rails.svg?style=svg)](https://circleci.com/gh/rubocop/rubocop-rails)
5
5
 
6
- A [RuboCop](https://github.com/rubocop-hq/rubocop) extension focused on enforcing Rails best practices and coding conventions.
6
+ A [RuboCop](https://github.com/rubocop/rubocop) extension focused on enforcing Rails best practices and coding conventions.
7
7
 
8
8
  Note: This repository manages rubocop-rails gem (>= 2.0.0). rubocop-rails gem (<= 1.5.0) has been renamed to [rubocop-rails_config](https://rubygems.org/gems/rubocop-rails_config) gem.
9
9
 
@@ -90,14 +90,14 @@ Rails cops support the following versions:
90
90
 
91
91
  If you use RuboCop Rails in your project, you can include one of these badges in your readme to let people know that your code is written following the community Rails Style Guide.
92
92
 
93
- [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop-rails)
93
+ [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop-rails)
94
94
 
95
95
  [![Rails Style Guide](https://img.shields.io/badge/code_style-community-brightgreen.svg)](https://rails.rubystyle.guide)
96
96
 
97
97
  Here are the Markdown snippets for the two badges:
98
98
 
99
99
  ``` markdown
100
- [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop-rails)
100
+ [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop-rails)
101
101
 
102
102
  [![Rails Style Guide](https://img.shields.io/badge/code_style-community-brightgreen.svg)](https://rails.rubystyle.guide)
103
103
  ```
data/config/default.yml CHANGED
@@ -17,6 +17,27 @@ AllCops:
17
17
  # as the default.
18
18
  TargetRailsVersion: ~
19
19
 
20
+ Lint/NumberConversion:
21
+ # Add Rails' duration methods to the ignore list for `Lint/NumberConversion`
22
+ # so that calling `to_i` on one of these does not register an offense.
23
+ # See: https://github.com/rubocop/rubocop/issues/8950
24
+ IgnoredMethods:
25
+ - ago
26
+ - from_now
27
+ - second
28
+ - seconds
29
+ - minute
30
+ - minutes
31
+ - hour
32
+ - hours
33
+ - day
34
+ - days
35
+ - week
36
+ - weeks
37
+ - fortnight
38
+ - fortnights
39
+ - in_milliseconds
40
+
20
41
  Rails/ActionFilter:
21
42
  Description: 'Enforces consistent use of action filter methods.'
22
43
  Enabled: true
@@ -128,8 +149,9 @@ Rails/BelongsTo:
128
149
  Rails/Blank:
129
150
  Description: 'Enforces use of `blank?`.'
130
151
  Enabled: true
152
+ SafeAutoCorrect: false
131
153
  VersionAdded: '0.48'
132
- VersionChanged: '0.67'
154
+ VersionChanged: '2.10'
133
155
  # Convert usages of `nil? || empty?` to `blank?`
134
156
  NilOrEmpty: true
135
157
  # Convert usages of `!present?` to `blank?`
@@ -207,8 +229,9 @@ Rails/DynamicFindBy:
207
229
  Description: 'Use `find_by` instead of dynamic `find_by_*`.'
208
230
  StyleGuide: 'https://rails.rubystyle.guide#find_by'
209
231
  Enabled: true
232
+ Safe: false
210
233
  VersionAdded: '0.44'
211
- VersionChanged: '2.6'
234
+ VersionChanged: '2.10'
212
235
  # The `Whitelist` has been deprecated, Please use `AllowedMethods` instead.
213
236
  Whitelist:
214
237
  - find_by_sql
@@ -237,6 +260,18 @@ Rails/EnvironmentComparison:
237
260
  Enabled: true
238
261
  VersionAdded: '0.52'
239
262
 
263
+ Rails/EnvironmentVariableAccess:
264
+ Description: 'Do not access `ENV` directly after initialization.'
265
+ Enabled: pending
266
+ VersionAdded: '2.10'
267
+ Include:
268
+ - app/**/*.rb
269
+ - lib/**/*.rb
270
+ Exclude:
271
+ - lib/**/*.rake
272
+ AllowReads: false
273
+ AllowWrites: false
274
+
240
275
  Rails/Exit:
241
276
  Description: >-
242
277
  Favor `fail`, `break`, `return`, etc. over `exit` in
@@ -540,7 +575,9 @@ Rails/RedundantReceiverInWithOptions:
540
575
  Rails/ReflectionClassName:
541
576
  Description: 'Use a string for `class_name` option value in the definition of a reflection.'
542
577
  Enabled: true
578
+ Safe: false
543
579
  VersionAdded: '0.64'
580
+ VersionChanged: '2.10'
544
581
 
545
582
  Rails/RefuteMethods:
546
583
  Description: 'Use `assert_not` methods instead of `refute` methods.'
@@ -583,6 +620,12 @@ Rails/RequestReferer:
583
620
  - referer
584
621
  - referrer
585
622
 
623
+ Rails/RequireDependency:
624
+ Description: 'Do not use `require_dependency` when running in Zeitwerk mode. `require_dependency` is for autoloading in classic mode.'
625
+ Reference: 'https://guides.rubyonrails.org/autoloading_and_reloading_constants.html'
626
+ Enabled: false
627
+ VersionAdded: '2.10'
628
+
586
629
  Rails/ReversibleMigration:
587
630
  Description: 'Checks whether the change method of the migration file is reversible.'
588
631
  StyleGuide: 'https://rails.rubystyle.guide#reversible-migration'
@@ -592,6 +635,13 @@ Rails/ReversibleMigration:
592
635
  Include:
593
636
  - db/migrate/*.rb
594
637
 
638
+ Rails/ReversibleMigrationMethodDefinition:
639
+ Description: 'Checks whether the migration implements either a `change` method or both an `up` and a `down` method.'
640
+ Enabled: false
641
+ VersionAdded: '2.10'
642
+ include:
643
+ - db/migrate/*.rb
644
+
595
645
  Rails/SafeNavigation:
596
646
  Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`."
597
647
  Enabled: true
@@ -687,13 +737,24 @@ Rails/TimeZone:
687
737
  Enabled: true
688
738
  Safe: false
689
739
  VersionAdded: '0.30'
690
- VersionChanged: '0.68'
740
+ VersionChanged: '2.10'
691
741
  # The value `strict` means that `Time` should be used with `zone`.
692
742
  # The value `flexible` allows usage of `in_time_zone` instead of `zone`.
693
743
  EnforcedStyle: flexible
694
744
  SupportedStyles:
695
745
  - strict
696
746
  - flexible
747
+ Exclude:
748
+ - '**/*.gemspec'
749
+
750
+ Rails/TimeZoneAssignment:
751
+ Description: 'Prefer the usage of `Time.use_zone` instead of manually updating `Time.zone` value.'
752
+ Reference: 'https://thoughtbot.com/blog/its-about-time-zones'
753
+ Enabled: 'pending'
754
+ VersionAdded: '2.10'
755
+ Include:
756
+ - spec/**/*.rb
757
+ - test/**/*.rb
697
758
 
698
759
  Rails/UniqBeforePluck:
699
760
  Description: 'Prefer the use of uniq or distinct before pluck.'
@@ -735,17 +796,20 @@ Rails/WhereEquals:
735
796
  Description: 'Pass conditions to `where` as a hash instead of manually constructing SQL.'
736
797
  StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
737
798
  Enabled: 'pending'
799
+ SafeAutoCorrect: false
738
800
  VersionAdded: '2.9'
801
+ VersionChanged: '2.10'
739
802
 
740
803
  Rails/WhereExists:
741
804
  Description: 'Prefer `exists?(...)` over `where(...).exists?`.'
742
805
  Enabled: 'pending'
806
+ SafeAutoCorrect: false
743
807
  EnforcedStyle: exists
744
808
  SupportedStyles:
745
809
  - exists
746
810
  - where
747
811
  VersionAdded: '2.7'
748
- VersionChanged: '2.8'
812
+ VersionChanged: '2.10'
749
813
 
750
814
  Rails/WhereNot:
751
815
  Description: 'Use `where.not(...)` instead of manually constructing negated SQL in `where`.'
@@ -0,0 +1,7 @@
1
+ #
2
+ # Configuration for obsoletion.
3
+ #
4
+ # See: https://docs.rubocop.org/rubocop/extensions.html#config-obsoletions
5
+ #
6
+ extracted:
7
+ Rails/*: ~
@@ -8,6 +8,13 @@ module RuboCop
8
8
 
9
9
  WHERE_METHODS = %i[where rewhere].freeze
10
10
 
11
+ def_node_matcher :active_record?, <<~PATTERN
12
+ {
13
+ (const nil? :ApplicationRecord)
14
+ (const (const nil? :ActiveRecord) :Base)
15
+ }
16
+ PATTERN
17
+
11
18
  def_node_search :find_set_table_name, <<~PATTERN
12
19
  (send self :table_name= {str sym})
13
20
  PATTERN
@@ -16,6 +23,10 @@ module RuboCop
16
23
  (send nil? :belongs_to {str sym} ...)
17
24
  PATTERN
18
25
 
26
+ def inherit_active_record_base?(node)
27
+ node.each_ancestor(:class).any? { |class_node| active_record?(class_node.parent_class) }
28
+ end
29
+
19
30
  def external_dependency_checksum
20
31
  return @external_dependency_checksum if defined?(@external_dependency_checksum)
21
32
 
@@ -75,7 +75,7 @@ module RuboCop
75
75
  def on_send(node)
76
76
  default_attribute(node) do |attribute|
77
77
  value = attribute.children.last
78
- return unless TYPE_OFFENDERS.any? { |type| value.type == type }
78
+ return unless TYPE_OFFENDERS.any?(value.type)
79
79
 
80
80
  add_offense(value) do |corrector|
81
81
  expression = default_attribute(node).children.last
@@ -68,7 +68,7 @@ module RuboCop
68
68
  RESTRICT_ON_SEND = %i[belongs_to].freeze
69
69
 
70
70
  def_node_matcher :match_belongs_to_with_options, <<~PATTERN
71
- (send _ :belongs_to _
71
+ (send _ :belongs_to ...
72
72
  (hash <$(pair (sym :required) ${true false}) ...>)
73
73
  )
74
74
  PATTERN
@@ -6,6 +6,10 @@ module RuboCop
6
6
  # This cop checks for code that can be written with simpler conditionals
7
7
  # using `Object#blank?` defined by Active Support.
8
8
  #
9
+ # This cop is marked as unsafe auto-correction, because `' '.empty?` returns false,
10
+ # but `' '.blank?` returns true. Therefore, auto-correction is not compatible
11
+ # if the receiver is a non-empty blank string, tab, or newline meta characters.
12
+ #
9
13
  # Interaction with `Style/UnlessElse`:
10
14
  # The configuration of `NotPresent` will not produce an offense in the
11
15
  # context of `unless else` if `Style/UnlessElse` is inabled. This is
@@ -28,19 +28,34 @@ module RuboCop
28
28
  MSG = 'Use `tag` instead of `content_tag`.'
29
29
  RESTRICT_ON_SEND = %i[content_tag].freeze
30
30
 
31
+ def on_new_investigation
32
+ @corrected_nodes = nil
33
+ end
34
+
31
35
  def on_send(node)
32
36
  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?
37
+ return if !first_argument ||
38
+ allowed_argument?(first_argument) ||
39
+ corrected_ancestor?(node)
36
40
 
37
41
  add_offense(node) do |corrector|
38
42
  autocorrect(corrector, node)
43
+
44
+ @corrected_nodes ||= Set.new.compare_by_identity
45
+ @corrected_nodes.add(node)
39
46
  end
40
47
  end
41
48
 
42
49
  private
43
50
 
51
+ def corrected_ancestor?(node)
52
+ node.each_ancestor(:send).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
53
+ end
54
+
55
+ def allowed_argument?(argument)
56
+ argument.variable? || argument.send_type? || argument.const_type? || argument.splat_type?
57
+ end
58
+
44
59
  def autocorrect(corrector, node)
45
60
  if method_name?(node.first_argument)
46
61
  range = correction_range(node)
@@ -32,13 +32,14 @@ module RuboCop
32
32
  # # good
33
33
  # Gem::Specification.find_by_name('backend').gem_dir
34
34
  class DynamicFindBy < Base
35
+ include ActiveRecordHelper
35
36
  extend AutoCorrector
36
37
 
37
38
  MSG = 'Use `%<static_name>s` instead of dynamic `%<method>s`.'
38
39
  METHOD_PATTERN = /^find_by_(.+?)(!)?$/.freeze
39
40
 
40
41
  def on_send(node)
41
- return if allowed_invocation?(node)
42
+ return if node.receiver.nil? && !inherit_active_record_base?(node) || allowed_invocation?(node)
42
43
 
43
44
  method_name = node.method_name
44
45
  static_name = static_method_name(method_name)
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop looks for direct access to environment variables through the
7
+ # `ENV` variable within the application code. This can lead to runtime
8
+ # errors due to misconfiguration that could have been discovered at boot
9
+ # time if the environment variables were loaded as part of initialization
10
+ # and copied into the application's configuration or secrets. The cop can
11
+ # be configured to allow either reads or writes if required.
12
+ #
13
+ # @example
14
+ # # good
15
+ # Rails.application.config.foo
16
+ # Rails.application.config.x.foo.bar
17
+ # Rails.application.secrets.foo
18
+ # Rails.application.config.foo = "bar"
19
+ #
20
+ # @example AllowReads: false (default)
21
+ # # bad
22
+ # ENV["FOO"]
23
+ # ENV.fetch("FOO")
24
+ #
25
+ # @example AllowReads: true
26
+ # # good
27
+ # ENV["FOO"]
28
+ # ENV.fetch("FOO")
29
+ #
30
+ # @example AllowWrites: false (default)
31
+ # # bad
32
+ # ENV["FOO"] = "bar"
33
+ #
34
+ # @example AllowWrites: true
35
+ # # good
36
+ # ENV["FOO"] = "bar"
37
+ class EnvironmentVariableAccess < Base
38
+ READ_MSG = 'Do not read from `ENV` directly post initialization.'
39
+ WRITE_MSG = 'Do not write to `ENV` directly post initialization.'
40
+
41
+ def on_const(node)
42
+ add_offense(node, message: READ_MSG) if env_read?(node) && !allow_reads?
43
+ add_offense(node, message: WRITE_MSG) if env_write?(node) && !allow_writes?
44
+ end
45
+
46
+ def_node_search :env_read?, <<~PATTERN
47
+ ^(send (const {cbase nil?} :ENV) !:[]= ...)
48
+ PATTERN
49
+
50
+ def_node_search :env_write?, <<~PATTERN
51
+ {^(indexasgn (const {cbase nil?} :ENV) ...)
52
+ ^(send (const {cbase nil?} :ENV) :[]= ...)}
53
+ PATTERN
54
+
55
+ private
56
+
57
+ def allow_reads?
58
+ cop_config['AllowReads'] == true
59
+ end
60
+
61
+ def allow_writes?
62
+ cop_config['AllowWrites'] == true
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -29,10 +29,8 @@ module RuboCop
29
29
  include ConfigurableEnforcedStyle
30
30
  include RangeHelp
31
31
 
32
- MSG_SLASHES = 'Please use `Rails.root.join(\'path/to\')` ' \
33
- 'instead.'
34
- MSG_ARGUMENTS = 'Please use `Rails.root.join(\'path\', \'to\')` ' \
35
- 'instead.'
32
+ MSG_SLASHES = 'Prefer `Rails.root.join(\'path/to\')`.'
33
+ MSG_ARGUMENTS = 'Prefer `Rails.root.join(\'path\', \'to\')`.'
36
34
  RESTRICT_ON_SEND = %i[join].freeze
37
35
 
38
36
  def_node_matcher :file_join_nodes?, <<~PATTERN
@@ -17,6 +17,7 @@ module RuboCop
17
17
  # # good
18
18
  # User.order(:foo).each
19
19
  class FindEach < Base
20
+ include ActiveRecordHelper
20
21
  extend AutoCorrector
21
22
 
22
23
  MSG = 'Use `find_each` instead of `each`.'
@@ -30,6 +31,7 @@ module RuboCop
30
31
  def on_send(node)
31
32
  return unless node.receiver&.send_type?
32
33
  return unless SCOPE_METHODS.include?(node.receiver.method_name)
34
+ return if node.receiver.receiver.nil? && !inherit_active_record_base?(node)
33
35
  return if ignored?(node)
34
36
 
35
37
  range = node.loc.selector
@@ -5,7 +5,9 @@ module RuboCop
5
5
  module Rails
6
6
  # This cop looks for `has_many` or `has_one` associations that don't
7
7
  # specify a `:dependent` option.
8
- # It doesn't register an offense if `:through` option was specified.
8
+ #
9
+ # It doesn't register an offense if `:through` or `dependent: nil`
10
+ # is specified, or if the model is read-only.
9
11
  #
10
12
  # @example
11
13
  # # bad
@@ -18,8 +20,18 @@ module RuboCop
18
20
  # class User < ActiveRecord::Base
19
21
  # has_many :comments, dependent: :restrict_with_exception
20
22
  # has_one :avatar, dependent: :destroy
23
+ # has_many :articles, dependent: nil
21
24
  # has_many :patients, through: :appointments
22
25
  # end
26
+ #
27
+ # class User < ActiveRecord::Base
28
+ # has_many :comments
29
+ # has_one :avatar
30
+ #
31
+ # def readonly?
32
+ # true
33
+ # end
34
+ # end
23
35
  class HasManyOrHasOneDependent < Base
24
36
  MSG = 'Specify a `:dependent` option.'
25
37
  RESTRICT_ON_SEND = %i[has_many has_one].freeze
@@ -37,7 +49,7 @@ module RuboCop
37
49
  PATTERN
38
50
 
39
51
  def_node_matcher :dependent_option?, <<~PATTERN
40
- (pair (sym :dependent) !nil)
52
+ (pair (sym :dependent) {!nil (nil)})
41
53
  PATTERN
42
54
 
43
55
  def_node_matcher :present_option?, <<~PATTERN
@@ -51,8 +63,20 @@ module RuboCop
51
63
  (args) ...)
52
64
  PATTERN
53
65
 
66
+ def_node_matcher :association_extension_block?, <<~PATTERN
67
+ (block
68
+ (send nil? :has_many _)
69
+ (args) ...)
70
+ PATTERN
71
+
72
+ def_node_matcher :readonly?, <<~PATTERN
73
+ (def :readonly?
74
+ (args)
75
+ (true))
76
+ PATTERN
77
+
54
78
  def on_send(node)
55
- return if active_resource?(node.parent)
79
+ return if active_resource?(node.parent) || readonly_model?(node)
56
80
  return if !association_without_options?(node) && valid_options?(association_with_options?(node))
57
81
  return if valid_options_in_with_options_block?(node)
58
82
 
@@ -61,10 +85,16 @@ module RuboCop
61
85
 
62
86
  private
63
87
 
88
+ def readonly_model?(node)
89
+ return false unless (parent = node.parent)
90
+
91
+ parent.each_descendant(:def).any? { |def_node| readonly?(def_node) }
92
+ end
93
+
64
94
  def valid_options_in_with_options_block?(node)
65
95
  return true unless node.parent
66
96
 
67
- n = node.parent.begin_type? ? node.parent.parent : node.parent
97
+ n = node.parent.begin_type? || association_extension_block?(node.parent) ? node.parent.parent : node.parent
68
98
 
69
99
  contain_valid_options_in_with_options_block?(n)
70
100
  end
@@ -18,6 +18,7 @@ module RuboCop
18
18
  # get :new, params: { user_id: 1 }
19
19
  # get :new, **options
20
20
  class HttpPositionalArguments < Base
21
+ include RangeHelp
21
22
  extend AutoCorrector
22
23
  extend TargetRailsVersion
23
24
 
@@ -44,7 +45,7 @@ module RuboCop
44
45
 
45
46
  message = format(MSG, verb: node.method_name)
46
47
 
47
- add_offense(node.loc.selector, message: message) do |corrector|
48
+ add_offense(highlight_range(node), message: message) do |corrector|
48
49
  # given a pre Rails 5 method: get :new, {user_id: @user.id}, {}
49
50
  #
50
51
  # @return lambda of auto correct procedure
@@ -80,6 +81,12 @@ module RuboCop
80
81
  node.sym_type? && node.value == :format
81
82
  end
82
83
 
84
+ def highlight_range(node)
85
+ _http_path, *data = *node.arguments
86
+
87
+ range_between(data.first.source_range.begin_pos, data.last.source_range.end_pos)
88
+ end
89
+
83
90
  def convert_hash_data(data, type)
84
91
  return '' if data.hash_type? && data.empty?
85
92
 
@@ -79,7 +79,11 @@ module RuboCop
79
79
  opening_quote = offence_node.children.last.source[0]
80
80
  closing_quote = opening_quote == ':' ? '' : opening_quote
81
81
  new_rel_exp = ", rel: #{opening_quote}noopener#{closing_quote}"
82
- range = send_node.arguments.last.source_range
82
+ range = if (last_argument = send_node.last_argument).hash_type?
83
+ last_argument.pairs.last.source_range
84
+ else
85
+ last_argument.source_range
86
+ end
83
87
 
84
88
  corrector.insert_after(range, new_rel_exp)
85
89
  end
@@ -5,6 +5,8 @@ module RuboCop
5
5
  module Rails
6
6
  # This cop checks if the value of the option `class_name`, in
7
7
  # the definition of a reflection is a string.
8
+ # It is marked as unsafe because it cannot be determined whether
9
+ # constant or method return value specified to `class_name` is a string.
8
10
  #
9
11
  # @example
10
12
  # # bad
@@ -16,6 +18,7 @@ module RuboCop
16
18
  class ReflectionClassName < Base
17
19
  MSG = 'Use a string value for `class_name`.'
18
20
  RESTRICT_ON_SEND = %i[has_many has_one belongs_to].freeze
21
+ ALLOWED_REFLECTION_CLASS_TYPES = %i[dstr str sym].freeze
19
22
 
20
23
  def_node_matcher :association_with_reflection, <<~PATTERN
21
24
  (send nil? {:has_many :has_one :belongs_to} _ _ ?
@@ -24,7 +27,7 @@ module RuboCop
24
27
  PATTERN
25
28
 
26
29
  def_node_matcher :reflection_class_name, <<~PATTERN
27
- (pair (sym :class_name) [!dstr !str !sym])
30
+ (pair (sym :class_name) #reflection_class_value?)
28
31
  PATTERN
29
32
 
30
33
  def on_send(node)
@@ -32,6 +35,16 @@ module RuboCop
32
35
  add_offense(reflection_class_name.loc.expression)
33
36
  end
34
37
  end
38
+
39
+ private
40
+
41
+ def reflection_class_value?(class_value)
42
+ if class_value.send_type?
43
+ !class_value.method?(:to_s) || class_value.receiver.const_type?
44
+ else
45
+ !ALLOWED_REFLECTION_CLASS_TYPES.include?(class_value.type)
46
+ end
47
+ end
35
48
  end
36
49
  end
37
50
  end
@@ -31,13 +31,18 @@ module RuboCop
31
31
  include RangeHelp
32
32
  extend AutoCorrector
33
33
 
34
- MSG = 'Do not assign %<method_name>s to constants as it ' \
34
+ MSG = 'Do not assign `%<method_name>s` to constants as it ' \
35
35
  'will be evaluated only once.'
36
+ RELATIVE_DATE_METHODS = %i[since from_now after ago until before yesterday tomorrow].freeze
36
37
 
37
38
  def on_casgn(node)
38
- relative_date_assignment?(node) do |method_name|
39
- add_offense(node, message: message(method_name)) do |corrector|
40
- autocorrect(corrector, node)
39
+ return if node.children[2]&.block_type?
40
+
41
+ node.each_descendant(:send) do |send_node|
42
+ relative_date?(send_node) do |method_name|
43
+ add_offense(node, message: message(method_name)) do |corrector|
44
+ autocorrect(corrector, node)
45
+ end
41
46
  end
42
47
  end
43
48
  end
@@ -88,23 +93,19 @@ module RuboCop
88
93
  range_between(name.loc.expression.begin_pos, value.loc.expression.end_pos)
89
94
  end
90
95
 
91
- def_node_matcher :relative_date_assignment?, <<~PATTERN
92
- {
93
- (casgn _ _ (send _ ${:since :from_now :after :ago :until :before}))
94
- (casgn _ _ ({erange irange} _ (send _ ${:since :from_now :after :ago :until :before})))
95
- (casgn _ _ ({erange irange} (send _ ${:since :from_now :after :ago :until :before}) _))
96
- }
97
- PATTERN
96
+ def relative_date_method?(method_name)
97
+ RELATIVE_DATE_METHODS.include?(method_name)
98
+ end
98
99
 
99
100
  def_node_matcher :relative_date_or_assignment?, <<~PATTERN
100
- (:or_asgn (casgn _ _) (send _ ${:since :from_now :after :ago :until :before}))
101
+ (:or_asgn (casgn _ _) (send _ $#relative_date_method?))
101
102
  PATTERN
102
103
 
103
104
  def_node_matcher :relative_date?, <<~PATTERN
104
105
  {
105
- ({erange irange} _ (send _ ${:since :from_now :after :ago :until :before}))
106
- ({erange irange} (send _ ${:since :from_now :after :ago :until :before}) _)
107
- (send _ ${:since :from_now :after :ago :until :before})
106
+ ({erange irange} _ (send _ $#relative_date_method?))
107
+ ({erange irange} (send _ $#relative_date_method?) _)
108
+ (send _ $#relative_date_method?)
108
109
  }
109
110
  PATTERN
110
111
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks for the usage of `require_dependency`.
7
+ #
8
+ # `require_dependency` is an obsolete method for Rails applications running in Zeitwerk mode.
9
+ # In Zeitwerk mode, the semantics should match Ruby's and no need to be defensive with load order,
10
+ # just refer to classes and modules normally.
11
+ # If the constant name is dynamic, camelize if needed, and constantize.
12
+ #
13
+ # Applications running in Zeitwerk mode should not use `require_dependency`.
14
+ #
15
+ # NOTE: This cop is disabled by default. Please enable it if you are using Zeitwerk mode.
16
+ #
17
+ # @example
18
+ # # bad
19
+ # require_dependency 'some_lib'
20
+ class RequireDependency < Base
21
+ extend TargetRailsVersion
22
+
23
+ minimum_target_rails_version 6.0
24
+
25
+ MSG = 'Do not use `require_dependency` with Zeitwerk mode.'
26
+ RESTRICT_ON_SEND = %i[require_dependency].freeze
27
+
28
+ def_node_matcher :require_dependency_call?, <<~PATTERN
29
+ (send {nil? (const _ :Kernel)} :require_dependency _)
30
+ PATTERN
31
+
32
+ def on_send(node)
33
+ require_dependency_call?(node) { add_offense(node) }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -237,7 +237,7 @@ module RuboCop
237
237
 
238
238
  def check_drop_table_node(node)
239
239
  drop_table_call(node) do
240
- unless node.parent.block_type?
240
+ unless node.parent.block_type? || node.last_argument.block_pass_type?
241
241
  add_offense(
242
242
  node,
243
243
  message: format(MSG, action: 'drop_table(without block)')
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks whether the migration implements
7
+ # either a `change` method or both an `up` and a `down`
8
+ # method.
9
+ #
10
+ # @example
11
+ # # bad
12
+ # class SomeMigration < ActiveRecord::Migration[6.0]
13
+ # def up
14
+ # # up migration
15
+ # end
16
+ #
17
+ # # <----- missing down method
18
+ # end
19
+ #
20
+ # class SomeMigration < ActiveRecord::Migration[6.0]
21
+ # # <----- missing up method
22
+ #
23
+ # def down
24
+ # # down migration
25
+ # end
26
+ # end
27
+ #
28
+ # # good
29
+ # class SomeMigration < ActiveRecord::Migration[6.0]
30
+ # def change
31
+ # # reversible migration
32
+ # end
33
+ # end
34
+ #
35
+ # # good
36
+ # class SomeMigration < ActiveRecord::Migration[6.0]
37
+ # def up
38
+ # # up migration
39
+ # end
40
+ #
41
+ # def down
42
+ # # down migration
43
+ # end
44
+ # end
45
+ class ReversibleMigrationMethodDefinition < Base
46
+ MSG = 'Migrations must contain either a `change` method, or ' \
47
+ 'both an `up` and a `down` method.'
48
+
49
+ def_node_matcher :migration_class?, <<~PATTERN
50
+ (class
51
+ (const nil? _)
52
+ (send
53
+ (const (const nil? :ActiveRecord) :Migration)
54
+ :[]
55
+ (float _))
56
+ _)
57
+ PATTERN
58
+
59
+ def_node_matcher :change_method?, <<~PATTERN
60
+ [ #migration_class? `(def :change (args) _) ]
61
+ PATTERN
62
+
63
+ def_node_matcher :up_and_down_methods?, <<~PATTERN
64
+ [ #migration_class? `(def :up (args) _) `(def :down (args) _) ]
65
+ PATTERN
66
+
67
+ def on_class(node)
68
+ return if change_method?(node) || up_and_down_methods?(node)
69
+
70
+ add_offense(node)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -44,9 +44,22 @@ module RuboCop
44
44
  RESTRICT_ON_SEND = %i[try try!].freeze
45
45
 
46
46
  def_node_matcher :try_call, <<~PATTERN
47
- (send !nil? ${:try :try!} $_ ...)
47
+ (send _ ${:try :try!} $_ ...)
48
48
  PATTERN
49
49
 
50
+ # Monkey patching for `Style/RedundantSelf` of RuboCop core.
51
+ # rubocop:disable Style/ClassAndModuleChildren
52
+ class Style::RedundantSelf
53
+ def self.autocorrect_incompatible_with
54
+ [Rails::SafeNavigation]
55
+ end
56
+ end
57
+ # rubocop:enable Style/ClassAndModuleChildren
58
+
59
+ def self.autocorrect_incompatible_with
60
+ [Style::RedundantSelf]
61
+ end
62
+
50
63
  def on_send(node)
51
64
  try_call(node) do |try_method, dispatch|
52
65
  return if try_method == :try && !cop_config['ConvertTry']
@@ -64,7 +77,12 @@ module RuboCop
64
77
  method_node, *params = *node.arguments
65
78
  method = method_node.source[1..-1]
66
79
 
67
- range = range_between(node.loc.dot.begin_pos, node.loc.expression.end_pos)
80
+ range = if node.receiver
81
+ range_between(node.loc.dot.begin_pos, node.loc.expression.end_pos)
82
+ else
83
+ corrector.insert_before(node, 'self')
84
+ node
85
+ end
68
86
 
69
87
  corrector.replace(range, replacement(method, params))
70
88
  end
@@ -19,7 +19,7 @@ module RuboCop
19
19
  #
20
20
  # # bad
21
21
  # Time.now
22
- # Time.parse('2015-03-02 19:05:37')
22
+ # Time.parse('2015-03-02T19:05:37')
23
23
  #
24
24
  # # bad
25
25
  # Time.current
@@ -27,18 +27,19 @@ module RuboCop
27
27
  #
28
28
  # # good
29
29
  # Time.zone.now
30
- # Time.zone.parse('2015-03-02 19:05:37')
30
+ # Time.zone.parse('2015-03-02T19:05:37')
31
+ # Time.zone.parse('2015-03-02T19:05:37Z') # Respect ISO 8601 format with timezone specifier.
31
32
  #
32
33
  # @example EnforcedStyle: flexible (default)
33
34
  # # `flexible` allows usage of `in_time_zone` instead of `zone`.
34
35
  #
35
36
  # # bad
36
37
  # Time.now
37
- # Time.parse('2015-03-02 19:05:37')
38
+ # Time.parse('2015-03-02T19:05:37')
38
39
  #
39
40
  # # good
40
41
  # Time.zone.now
41
- # Time.zone.parse('2015-03-02 19:05:37')
42
+ # Time.zone.parse('2015-03-02T19:05:37')
42
43
  #
43
44
  # # good
44
45
  # Time.current
@@ -63,6 +64,8 @@ module RuboCop
63
64
  ACCEPTED_METHODS = %i[in_time_zone utc getlocal xmlschema iso8601
64
65
  jisx0301 rfc3339 httpdate to_i to_f].freeze
65
66
 
67
+ TIMEZONE_SPECIFIER = /[A-z]/.freeze
68
+
66
69
  def on_const(node)
67
70
  mod, klass = *node
68
71
  # we should only check core classes
@@ -116,9 +119,10 @@ module RuboCop
116
119
  end
117
120
 
118
121
  def check_time_node(klass, node)
122
+ return if attach_timezone_specifier?(node.first_argument)
123
+
119
124
  chain = extract_method_chain(node)
120
125
  return if not_danger_chain?(chain)
121
-
122
126
  return check_localtime(node) if need_check_localtime?(chain)
123
127
 
124
128
  method_name = (chain & DANGEROUS_METHODS).join('.')
@@ -132,6 +136,10 @@ module RuboCop
132
136
  end
133
137
  end
134
138
 
139
+ def attach_timezone_specifier?(date)
140
+ date.respond_to?(:value) && TIMEZONE_SPECIFIER.match?(date.value.to_s[-1])
141
+ end
142
+
135
143
  def build_message(klass, method_name, node)
136
144
  if flexible?
137
145
  format(
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks for the use of `Time.zone=` method.
7
+ #
8
+ # The `zone` attribute persists for the rest of the Ruby runtime, potentially causing
9
+ # unexpected behaviour at a later time.
10
+ # Using `Time.use_zone` ensures the code passed in block is the only place Time.zone is affected.
11
+ # It eliminates the possibility of a `zone` sticking around longer than intended.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # Time.zone = 'EST'
16
+ #
17
+ # # good
18
+ # Time.use_zone('EST') do
19
+ # end
20
+ #
21
+ class TimeZoneAssignment < Base
22
+ MSG = 'Use `Time.use_zone` with blocks instead of `Time.zone=`.'
23
+ RESTRICT_ON_SEND = %i[zone=].freeze
24
+
25
+ def_node_matcher :time_zone_assignement?, <<~PATTERN
26
+ (send (const nil? :Time) :zone= ...)
27
+ PATTERN
28
+
29
+ def on_send(node)
30
+ return unless time_zone_assignement?(node)
31
+
32
+ add_offense(node)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -62,7 +62,7 @@ module RuboCop
62
62
  # DidYouMean::SpellChecker is not available in all versions of Ruby,
63
63
  # and even on versions where it *is* available (>= 2.3), it is not
64
64
  # always required correctly. So we do a feature check first. See:
65
- # https://github.com/rubocop-hq/rubocop/issues/7979
65
+ # https://github.com/rubocop/rubocop/issues/7979
66
66
  similar_names = if defined?(DidYouMean::SpellChecker)
67
67
  spell_checker = DidYouMean::SpellChecker.new(dictionary: environments)
68
68
  spell_checker.correct(name)
@@ -11,6 +11,17 @@ module RuboCop
11
11
  # When EnforcedStyle is 'where' then the cop enforces
12
12
  # `where(...).exists?` over `exists?(...)`.
13
13
  #
14
+ # This cop is unsafe for auto-correction because the behavior may change on the following case:
15
+ #
16
+ # [source,ruby]
17
+ # ----
18
+ # Author.includes(:articles).where(articles: {id: id}).exists?
19
+ # #=> Perform `eager_load` behavior (`LEFT JOIN` query) and get result.
20
+ #
21
+ # Author.includes(:articles).exists?(articles: {id: id})
22
+ # #=> Perform `preload` behavior and `ActiveRecord::StatementInvalid` error occurs.
23
+ # ----
24
+ #
14
25
  # @example EnforcedStyle: exists (default)
15
26
  # # bad
16
27
  # User.where(name: 'john').exists?
@@ -15,11 +15,13 @@ module RuboCop
15
15
  # User.where('name IS NOT NULL')
16
16
  # User.where('name NOT IN (?)', ['john', 'jane'])
17
17
  # User.where('name NOT IN (:names)', names: ['john', 'jane'])
18
+ # User.where('users.name != :name', name: 'Gabe')
18
19
  #
19
20
  # # good
20
21
  # User.where.not(name: 'Gabe')
21
22
  # User.where.not(name: nil)
22
23
  # User.where.not(name: ['john', 'jane'])
24
+ # User.where.not(users: { name: 'Gabe' })
23
25
  #
24
26
  class WhereNot < Base
25
27
  include RangeHelp
@@ -86,7 +88,9 @@ module RuboCop
86
88
 
87
89
  def build_good_method(column, value)
88
90
  if column.include?('.')
89
- "where.not('#{column}' => #{value})"
91
+ table, column = column.split('.')
92
+
93
+ "where.not(#{table}: { #{column}: #{value} })"
90
94
  else
91
95
  "where.not(#{column}: #{value})"
92
96
  end
@@ -31,6 +31,7 @@ require_relative 'rails/dynamic_find_by'
31
31
  require_relative 'rails/enum_hash'
32
32
  require_relative 'rails/enum_uniqueness'
33
33
  require_relative 'rails/environment_comparison'
34
+ require_relative 'rails/environment_variable_access'
34
35
  require_relative 'rails/exit'
35
36
  require_relative 'rails/file_path'
36
37
  require_relative 'rails/find_by'
@@ -73,7 +74,9 @@ require_relative 'rails/relative_date_constant'
73
74
  require_relative 'rails/render_inline'
74
75
  require_relative 'rails/render_plain_text'
75
76
  require_relative 'rails/request_referer'
77
+ require_relative 'rails/require_dependency'
76
78
  require_relative 'rails/reversible_migration'
79
+ require_relative 'rails/reversible_migration_method_definition'
77
80
  require_relative 'rails/safe_navigation'
78
81
  require_relative 'rails/safe_navigation_with_blank'
79
82
  require_relative 'rails/save_bang'
@@ -82,6 +85,7 @@ require_relative 'rails/short_i18n'
82
85
  require_relative 'rails/skips_model_validations'
83
86
  require_relative 'rails/squished_sql_heredocs'
84
87
  require_relative 'rails/time_zone'
88
+ require_relative 'rails/time_zone_assignment'
85
89
  require_relative 'rails/uniq_before_pluck'
86
90
  require_relative 'rails/unique_validation_without_index'
87
91
  require_relative 'rails/unknown_env'
data/lib/rubocop/rails.rb CHANGED
@@ -8,5 +8,7 @@ module RuboCop
8
8
  CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze
9
9
 
10
10
  private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
11
+
12
+ ::RuboCop::ConfigObsoletion.files << PROJECT_ROOT.join('config', 'obsoletion.yml')
11
13
  end
12
14
  end
@@ -128,9 +128,7 @@ module RuboCop
128
128
  return unless pairs.hash_type?
129
129
 
130
130
  pairs.each_pair do |k, v|
131
- if k.value == :null
132
- @not_null = v.true_type? ? false : true
133
- end
131
+ @not_null = !v.true_type? if k.value == :null
134
132
  end
135
133
  end
136
134
  end
@@ -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.9.1'
7
+ STRING = '2.10.0'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
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.9.1
4
+ version: 2.10.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-12-16 00:00:00.000000000 Z
13
+ date: 2021-05-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -46,7 +46,7 @@ dependencies:
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 0.90.0
49
+ version: 1.7.0
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '2.0'
@@ -56,7 +56,7 @@ dependencies:
56
56
  requirements:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 0.90.0
59
+ version: 1.7.0
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '2.0'
@@ -74,6 +74,7 @@ files:
74
74
  - README.md
75
75
  - bin/setup
76
76
  - config/default.yml
77
+ - config/obsoletion.yml
77
78
  - lib/rubocop-rails.rb
78
79
  - lib/rubocop/cop/mixin/active_record_helper.rb
79
80
  - lib/rubocop/cop/mixin/enforce_superclass.rb
@@ -105,6 +106,7 @@ files:
105
106
  - lib/rubocop/cop/rails/enum_hash.rb
106
107
  - lib/rubocop/cop/rails/enum_uniqueness.rb
107
108
  - lib/rubocop/cop/rails/environment_comparison.rb
109
+ - lib/rubocop/cop/rails/environment_variable_access.rb
108
110
  - lib/rubocop/cop/rails/exit.rb
109
111
  - lib/rubocop/cop/rails/file_path.rb
110
112
  - lib/rubocop/cop/rails/find_by.rb
@@ -147,7 +149,9 @@ files:
147
149
  - lib/rubocop/cop/rails/render_inline.rb
148
150
  - lib/rubocop/cop/rails/render_plain_text.rb
149
151
  - lib/rubocop/cop/rails/request_referer.rb
152
+ - lib/rubocop/cop/rails/require_dependency.rb
150
153
  - lib/rubocop/cop/rails/reversible_migration.rb
154
+ - lib/rubocop/cop/rails/reversible_migration_method_definition.rb
151
155
  - lib/rubocop/cop/rails/safe_navigation.rb
152
156
  - lib/rubocop/cop/rails/safe_navigation_with_blank.rb
153
157
  - lib/rubocop/cop/rails/save_bang.rb
@@ -156,6 +160,7 @@ files:
156
160
  - lib/rubocop/cop/rails/skips_model_validations.rb
157
161
  - lib/rubocop/cop/rails/squished_sql_heredocs.rb
158
162
  - lib/rubocop/cop/rails/time_zone.rb
163
+ - lib/rubocop/cop/rails/time_zone_assignment.rb
159
164
  - lib/rubocop/cop/rails/uniq_before_pluck.rb
160
165
  - lib/rubocop/cop/rails/unique_validation_without_index.rb
161
166
  - lib/rubocop/cop/rails/unknown_env.rb
@@ -169,15 +174,15 @@ files:
169
174
  - lib/rubocop/rails/schema_loader.rb
170
175
  - lib/rubocop/rails/schema_loader/schema.rb
171
176
  - lib/rubocop/rails/version.rb
172
- homepage: https://github.com/rubocop-hq/rubocop-rails
177
+ homepage: https://github.com/rubocop/rubocop-rails
173
178
  licenses:
174
179
  - MIT
175
180
  metadata:
176
181
  homepage_uri: https://docs.rubocop.org/rubocop-rails/
177
- changelog_uri: https://github.com/rubocop-hq/rubocop-rails/blob/master/CHANGELOG.md
178
- source_code_uri: https://github.com/rubocop-hq/rubocop-rails/
179
- documentation_uri: https://docs.rubocop.org/rubocop-rails/2.9/
180
- bug_tracker_uri: https://github.com/rubocop-hq/rubocop-rails/issues
182
+ changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
183
+ source_code_uri: https://github.com/rubocop/rubocop-rails/
184
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/2.10/
185
+ bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
181
186
  post_install_message:
182
187
  rdoc_options: []
183
188
  require_paths:
@@ -186,14 +191,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
186
191
  requirements:
187
192
  - - ">="
188
193
  - !ruby/object:Gem::Version
189
- version: 2.4.0
194
+ version: 2.5.0
190
195
  required_rubygems_version: !ruby/object:Gem::Requirement
191
196
  requirements:
192
197
  - - ">="
193
198
  - !ruby/object:Gem::Version
194
199
  version: '0'
195
200
  requirements: []
196
- rubygems_version: 3.2.1
201
+ rubygems_version: 3.2.16
197
202
  signing_key:
198
203
  specification_version: 4
199
204
  summary: Automatic Rails code style checking tool.