rubocop-rails 2.15.2 → 2.16.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +80 -0
  3. data/config/obsoletion.yml +10 -0
  4. data/lib/rubocop/cop/mixin/active_record_helper.rb +1 -4
  5. data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +1 -3
  6. data/lib/rubocop/cop/mixin/index_method.rb +5 -15
  7. data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +98 -0
  8. data/lib/rubocop/cop/rails/action_filter.rb +1 -1
  9. data/lib/rubocop/cop/rails/active_record_aliases.rb +1 -4
  10. data/lib/rubocop/cop/rails/active_record_override.rb +2 -5
  11. data/lib/rubocop/cop/rails/active_support_on_load.rb +70 -0
  12. data/lib/rubocop/cop/rails/add_column_index.rb +1 -4
  13. data/lib/rubocop/cop/rails/blank.rb +1 -2
  14. data/lib/rubocop/cop/rails/bulk_change_table.rb +6 -20
  15. data/lib/rubocop/cop/rails/compact_blank.rb +5 -1
  16. data/lib/rubocop/cop/rails/content_tag.rb +1 -3
  17. data/lib/rubocop/cop/rails/date.rb +4 -9
  18. data/lib/rubocop/cop/rails/delegate.rb +2 -5
  19. data/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +17 -13
  20. data/lib/rubocop/cop/rails/dot_separated_keys.rb +1 -1
  21. data/lib/rubocop/cop/rails/dynamic_find_by.rb +2 -4
  22. data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -5
  23. data/lib/rubocop/cop/rails/environment_comparison.rb +1 -2
  24. data/lib/rubocop/cop/rails/file_path.rb +2 -4
  25. data/lib/rubocop/cop/rails/find_each.rb +8 -2
  26. data/lib/rubocop/cop/rails/freeze_time.rb +69 -0
  27. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -3
  28. data/lib/rubocop/cop/rails/http_positional_arguments.rb +4 -9
  29. data/lib/rubocop/cop/rails/http_status.rb +5 -10
  30. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +3 -10
  31. data/lib/rubocop/cop/rails/inverse_of.rb +3 -6
  32. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +2 -6
  33. data/lib/rubocop/cop/rails/link_to_blank.rb +1 -4
  34. data/lib/rubocop/cop/rails/output.rb +2 -5
  35. data/lib/rubocop/cop/rails/pluralization_grammar.rb +1 -2
  36. data/lib/rubocop/cop/rails/presence.rb +1 -3
  37. data/lib/rubocop/cop/rails/present.rb +3 -6
  38. data/lib/rubocop/cop/rails/rake_environment.rb +1 -1
  39. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +2 -4
  40. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
  41. data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +2 -2
  42. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +28 -26
  43. data/lib/rubocop/cop/rails/reflection_class_name.rb +17 -0
  44. data/lib/rubocop/cop/rails/refute_methods.rb +1 -5
  45. data/lib/rubocop/cop/rails/relative_date_constant.rb +2 -5
  46. data/lib/rubocop/cop/rails/request_referer.rb +1 -2
  47. data/lib/rubocop/cop/rails/reversible_migration.rb +10 -33
  48. data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +1 -2
  49. data/lib/rubocop/cop/rails/root_pathname_methods.rb +175 -0
  50. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +1 -3
  51. data/lib/rubocop/cop/rails/save_bang.rb +10 -22
  52. data/lib/rubocop/cop/rails/short_i18n.rb +1 -4
  53. data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -2
  54. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -5
  55. data/lib/rubocop/cop/rails/time_zone.rb +8 -19
  56. data/lib/rubocop/cop/rails/to_s_with_argument.rb +41 -0
  57. data/lib/rubocop/cop/rails/top_level_hash_with_indifferent_access.rb +48 -0
  58. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +3 -6
  59. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -3
  60. data/lib/rubocop/cop/rails/unknown_env.rb +2 -4
  61. data/lib/rubocop/cop/rails/validation.rb +4 -12
  62. data/lib/rubocop/cop/rails/where_missing.rb +111 -0
  63. data/lib/rubocop/cop/rails_cops.rb +7 -0
  64. data/lib/rubocop/rails/version.rb +1 -1
  65. metadata +13 -8
  66. data/bin/console +0 -11
  67. data/bin/setup +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 169ed04b1f5378e9e08fbffdca151afaf4b84fd54b1867a173740aadaede60b3
4
- data.tar.gz: 1a2ac75c313cfcdeec1814d7e3aff4777c5013527d2cf4a2aa4f95aeb45446bf
3
+ metadata.gz: a928896af6bef8228bfc2530b829a683154c23b22ea547557d40ea1e4d08ae7f
4
+ data.tar.gz: 40303c4d80e1e6eaef12ceb0170b64b65b151fc2056957d6c6b6bac1d645d445
5
5
  SHA512:
6
- metadata.gz: 51d495edd3e825db49ece8f51bfc118c73887681f414b86d31cd47d85dc5a1a22a385a2a17ed4ebf7d1c6332989795e2cde999a364d911c60f452993dc926c4b
7
- data.tar.gz: 4546785b39af93e6c7fe5a6a3b637fa5c21d4b358c38ea8ad3ebd5c272d1d0a504e8206e8201cfe3771af9199c336649d033e32b324f16b06fc7d150054dc488
6
+ metadata.gz: a87b9c167cf43287207bae3ec38e385cb6213c26ff0f7e10aa3bf392ab28b724794820a459dc6af6d464e48ea70629c443e74acc4539dca6f0c0a57fee65d87c
7
+ data.tar.gz: fbb0b7333c6d485e50facadd7170bb2d59e425119134d01f42ac3d24eecc01ad52d588f55de184c9373061ba207cf6845d3e8201fe43ce48e3a8d3b22e992dff
data/config/default.yml CHANGED
@@ -10,6 +10,9 @@ AllCops:
10
10
  # Exclude db/schema.rb and db/[CONFIGURATION_NAMESPACE]_schema.rb by default.
11
11
  # See: https://guides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application
12
12
  - db/*schema.rb
13
+ # Enable checking Active Support extensions.
14
+ # See: https://docs.rubocop.org/rubocop/configuration.html#enable-checking-active-support-extensions
15
+ ActiveSupportExtensionsEnabled: true
13
16
  # What version of Rails is the inspected code using? If a value is specified
14
17
  # for TargetRailsVersion then it is used. Acceptable values are specified
15
18
  # as a float (i.e. 5.1); the patch version of Rails should not be included.
@@ -23,6 +26,24 @@ Lint/NumberConversion:
23
26
  # Add Rails' duration methods to the ignore list for `Lint/NumberConversion`
24
27
  # so that calling `to_i` on one of these does not register an offense.
25
28
  # See: https://github.com/rubocop/rubocop/issues/8950
29
+ AllowedMethods:
30
+ - ago
31
+ - from_now
32
+ - second
33
+ - seconds
34
+ - minute
35
+ - minutes
36
+ - hour
37
+ - hours
38
+ - day
39
+ - days
40
+ - week
41
+ - weeks
42
+ - fortnight
43
+ - fortnights
44
+ - in_milliseconds
45
+ AllowedPatterns: []
46
+ # Deprecated.
26
47
  IgnoredMethods:
27
48
  - ago
28
49
  - from_now
@@ -40,6 +61,18 @@ Lint/NumberConversion:
40
61
  - fortnights
41
62
  - in_milliseconds
42
63
 
64
+ Rails:
65
+ Enabled: true
66
+ DocumentationBaseURL: https://docs.rubocop.org/rubocop-rails
67
+
68
+ Rails/ActionControllerFlashBeforeRender:
69
+ Description: 'Use `flash.now` instead of `flash` before `render`.'
70
+ StyleGuide: 'https://rails.rubystyle.guide/#flash-before-render'
71
+ Reference: 'https://api.rubyonrails.org/classes/ActionController/FlashBeforeRender.html'
72
+ Enabled: 'pending'
73
+ SafeAutocorrect: false
74
+ VersionAdded: '2.16'
75
+
43
76
  Rails/ActionControllerTestCase:
44
77
  Description: 'Use `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.'
45
78
  StyleGuide: 'https://rails.rubystyle.guide/#integration-testing'
@@ -96,6 +129,15 @@ Rails/ActiveSupportAliases:
96
129
  Enabled: true
97
130
  VersionAdded: '0.48'
98
131
 
132
+ Rails/ActiveSupportOnLoad:
133
+ Description: 'Use `ActiveSupport.on_load(...)` to patch Rails framework classes.'
134
+ Enabled: 'pending'
135
+ Reference:
136
+ - 'https://api.rubyonrails.org/classes/ActiveSupport/LazyLoadHooks.html'
137
+ - 'https://guides.rubyonrails.org/engines.html#available-load-hooks'
138
+ SafeAutoCorrect: false
139
+ VersionAdded: '2.16'
140
+
99
141
  Rails/AddColumnIndex:
100
142
  Description: >-
101
143
  Rails migrations don't make use of a given `index` key, but also
@@ -407,6 +449,14 @@ Rails/FindEach:
407
449
  VersionChanged: '2.9'
408
450
  Include:
409
451
  - app/models/**/*.rb
452
+ AllowedMethods:
453
+ # Methods that don't work well with `find_each`.
454
+ - order
455
+ - limit
456
+ - select
457
+ - lock
458
+ AllowedPatterns: []
459
+ # Deprecated.
410
460
  IgnoredMethods:
411
461
  # Methods that don't work well with `find_each`.
412
462
  - order
@@ -414,6 +464,13 @@ Rails/FindEach:
414
464
  - select
415
465
  - lock
416
466
 
467
+ Rails/FreezeTime:
468
+ Description: 'Prefer `freeze_time` over `travel_to` with an argument of the current time.'
469
+ StyleGuide: 'https://rails.rubystyle.guide/#freeze-time'
470
+ Enabled: pending
471
+ VersionAdded: '2.16'
472
+ SafeAutoCorrect: false
473
+
417
474
  Rails/HasAndBelongsToMany:
418
475
  Description: 'Prefer has_many :through to has_and_belongs_to_many.'
419
476
  StyleGuide: 'https://rails.rubystyle.guide#has-many-through'
@@ -785,6 +842,11 @@ Rails/RootJoinChain:
785
842
  Enabled: pending
786
843
  VersionAdded: '2.13'
787
844
 
845
+ Rails/RootPathnameMethods:
846
+ Description: 'Use `Rails.root` IO methods instead of passing it to `File`.'
847
+ Enabled: pending
848
+ VersionAdded: '2.16'
849
+
788
850
  Rails/RootPublicPath:
789
851
  Description: "Favor `Rails.public_path` over `Rails.root` with `'public'`."
790
852
  Enabled: pending
@@ -937,6 +999,18 @@ Rails/ToFormattedS:
937
999
  - to_formatted_s
938
1000
  VersionAdded: '2.15'
939
1001
 
1002
+ Rails/ToSWithArgument:
1003
+ Description: 'Identifies passing any argument to `#to_s`.'
1004
+ Enabled: pending
1005
+ Safe: false
1006
+ VersionAdded: '2.16'
1007
+
1008
+ Rails/TopLevelHashWithIndifferentAccess:
1009
+ Description: 'Identifies top-level `HashWithIndifferentAccess`.'
1010
+ Reference: 'https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#top-level-hashwithindifferentaccess-is-soft-deprecated'
1011
+ Enabled: pending
1012
+ VersionAdded: '2.16'
1013
+
940
1014
  Rails/TransactionExitStatement:
941
1015
  Description: 'Avoid the usage of `return`, `break` and `throw` in transaction blocks.'
942
1016
  Enabled: pending
@@ -1003,6 +1077,12 @@ Rails/WhereExists:
1003
1077
  VersionAdded: '2.7'
1004
1078
  VersionChanged: '2.10'
1005
1079
 
1080
+ Rails/WhereMissing:
1081
+ Description: 'Use `where.missing(...)` to find missing relationship records.'
1082
+ StyleGuide: 'https://rails.rubystyle.guide/#finding-missing-relationship-records'
1083
+ Enabled: pending
1084
+ VersionAdded: '2.16'
1085
+
1006
1086
  Rails/WhereNot:
1007
1087
  Description: 'Use `where.not(...)` instead of manually constructing negated SQL in `where`.'
1008
1088
  StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
@@ -5,3 +5,13 @@
5
5
  #
6
6
  extracted:
7
7
  Rails/*: ~
8
+
9
+ # Cop parameters that have been changed
10
+ # Can be treated as a warning instead of a failure with `severity: warning`
11
+ changed_parameters:
12
+ - cops: Rails/FindEach
13
+ parameters: IgnoredMethods
14
+ alternatives:
15
+ - AllowedMethods
16
+ - AllowedPatterns
17
+ severity: warning
@@ -48,10 +48,7 @@ module RuboCop
48
48
 
49
49
  class_nodes = class_node.defined_module.each_node
50
50
  namespaces = class_node.each_ancestor(:class, :module).map(&:identifier)
51
- [*class_nodes, *namespaces]
52
- .reverse
53
- .map { |node| node.children[1] }.join('_')
54
- .tableize
51
+ [*class_nodes, *namespaces].reverse.map { |node| node.children[1] }.join('_').tableize
55
52
  end
56
53
 
57
54
  # Resolve relation into column name.
@@ -10,9 +10,7 @@ module RuboCop
10
10
  bigint binary boolean date datetime decimal float integer json string
11
11
  text time timestamp virtual
12
12
  ].freeze
13
- RAILS_ABSTRACT_SCHEMA_DEFINITIONS_HELPERS = %i[
14
- column references belongs_to primary_key numeric
15
- ].freeze
13
+ RAILS_ABSTRACT_SCHEMA_DEFINITIONS_HELPERS = %i[column references belongs_to primary_key numeric].freeze
16
14
  POSTGRES_SCHEMA_DEFINITIONS = %i[
17
15
  bigserial bit bit_varying cidr citext daterange hstore inet interval
18
16
  int4range int8range jsonb ltree macaddr money numrange oid point line
@@ -6,7 +6,7 @@ module RuboCop
6
6
  module IndexMethod # rubocop:disable Metrics/ModuleLength
7
7
  RESTRICT_ON_SEND = %i[each_with_object to_h map collect []].freeze
8
8
 
9
- def on_block(node)
9
+ def on_block(node) # rubocop:todo InternalAffairs/NumblockHandler
10
10
  on_bad_each_with_object(node) do |*match|
11
11
  handle_possible_offense(node, match, 'each_with_object')
12
12
  end
@@ -98,10 +98,7 @@ module RuboCop
98
98
 
99
99
  captures = extract_captures(correction.match)
100
100
  correction.set_new_arg_name(captures.transformed_argname, corrector)
101
- correction.set_new_body_expression(
102
- captures.transforming_body_expr,
103
- corrector
104
- )
101
+ correction.set_new_body_expression(captures.transforming_body_expr, corrector)
105
102
  end
106
103
 
107
104
  # Internal helper class to hold match data
@@ -110,8 +107,7 @@ module RuboCop
110
107
  :transforming_body_expr
111
108
  ) do
112
109
  def noop_transformation?
113
- transforming_body_expr.lvar_type? &&
114
- transforming_body_expr.children == [transformed_argname]
110
+ transforming_body_expr.lvar_type? && transforming_body_expr.children == [transformed_argname]
115
111
  end
116
112
  end
117
113
 
@@ -157,17 +153,11 @@ module RuboCop
157
153
  end
158
154
 
159
155
  def set_new_arg_name(transformed_argname, corrector)
160
- corrector.replace(
161
- block_node.arguments.loc.expression,
162
- "|#{transformed_argname}|"
163
- )
156
+ corrector.replace(block_node.arguments.loc.expression, "|#{transformed_argname}|")
164
157
  end
165
158
 
166
159
  def set_new_body_expression(transforming_body_expr, corrector)
167
- corrector.replace(
168
- block_node.body.loc.expression,
169
- transforming_body_expr.loc.expression.source
170
- )
160
+ corrector.replace(block_node.body.loc.expression, transforming_body_expr.loc.expression.source)
171
161
  end
172
162
  end
173
163
  end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Using `flash` assignment before `render` in Rails controllers will persist the message for too long.
7
+ # Check https://guides.rubyonrails.org/action_controller_overview.html#flash-now
8
+ #
9
+ # @safety
10
+ # This cop's autocorrection is unsafe because it replaces `flash` by `flash.now`.
11
+ # Even though it is usually a mistake, it might be used intentionally.
12
+ #
13
+ # @example
14
+ #
15
+ # # bad
16
+ # class HomeController < ApplicationController
17
+ # def create
18
+ # flash[:alert] = "msg"
19
+ # render :index
20
+ # end
21
+ # end
22
+ #
23
+ # # good
24
+ # class HomeController < ApplicationController
25
+ # def create
26
+ # flash.now[:alert] = "msg"
27
+ # render :index
28
+ # end
29
+ # end
30
+ #
31
+ class ActionControllerFlashBeforeRender < Base
32
+ extend AutoCorrector
33
+
34
+ MSG = 'Use `flash.now` before `render`.'
35
+
36
+ def_node_search :flash_assignment?, <<~PATTERN
37
+ ^(send (send nil? :flash) :[]= ...)
38
+ PATTERN
39
+
40
+ def_node_search :render?, <<~PATTERN
41
+ (send nil? :render ...)
42
+ PATTERN
43
+
44
+ def_node_search :action_controller?, <<~PATTERN
45
+ {
46
+ (const nil? :ApplicationController)
47
+ (const (const nil? :ActionController) :Base)
48
+ }
49
+ PATTERN
50
+
51
+ RESTRICT_ON_SEND = [:flash].freeze
52
+
53
+ def on_send(flash_node)
54
+ return unless flash_assignment?(flash_node)
55
+
56
+ return unless followed_by_render?(flash_node)
57
+
58
+ return unless instance_method_or_block?(flash_node)
59
+
60
+ return unless inherit_action_controller_base?(flash_node)
61
+
62
+ add_offense(flash_node) do |corrector|
63
+ corrector.replace(flash_node, 'flash.now')
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def followed_by_render?(flash_node)
70
+ flash_assigment_node = find_ancestor(flash_node, type: :send)
71
+ context = flash_assigment_node.parent
72
+
73
+ context.each_child_node.any? do |node|
74
+ render?(node)
75
+ end
76
+ end
77
+
78
+ def inherit_action_controller_base?(node)
79
+ class_node = find_ancestor(node, type: :class)
80
+ return unless class_node
81
+
82
+ action_controller?(class_node)
83
+ end
84
+
85
+ def instance_method_or_block?(node)
86
+ def_node = find_ancestor(node, type: :def)
87
+ block_node = find_ancestor(node, type: :block)
88
+
89
+ def_node || block_node
90
+ end
91
+
92
+ def find_ancestor(node, type:)
93
+ node.each_ancestor(type).first
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -69,7 +69,7 @@ module RuboCop
69
69
 
70
70
  RESTRICT_ON_SEND = FILTER_METHODS + ACTION_METHODS
71
71
 
72
- def on_block(node)
72
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
73
73
  check_method_node(node.send_node)
74
74
  end
75
75
 
@@ -21,10 +21,7 @@ module RuboCop
21
21
 
22
22
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
23
23
 
24
- ALIASES = {
25
- update_attributes: :update,
26
- update_attributes!: :update!
27
- }.freeze
24
+ ALIASES = { update_attributes: :update, update_attributes!: :update! }.freeze
28
25
 
29
26
  RESTRICT_ON_SEND = ALIASES.keys.freeze
30
27
 
@@ -25,12 +25,9 @@ module RuboCop
25
25
  # end
26
26
  #
27
27
  class ActiveRecordOverride < Base
28
- MSG =
29
- 'Use %<prefer>s callbacks instead of overriding the Active Record ' \
30
- 'method `%<bad>s`.'
28
+ MSG = 'Use %<prefer>s callbacks instead of overriding the Active Record method `%<bad>s`.'
31
29
  BAD_METHODS = %i[create destroy save update].freeze
32
- ACTIVE_RECORD_CLASSES = %w[ApplicationRecord ActiveModel::Base
33
- ActiveRecord::Base].freeze
30
+ ACTIVE_RECORD_CLASSES = %w[ApplicationRecord ActiveModel::Base ActiveRecord::Base].freeze
34
31
 
35
32
  def on_def(node)
36
33
  return unless BAD_METHODS.include?(node.method_name)
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Checks for Rails framework classes that are patched directly instead of using Active Support load hooks. Direct
7
+ # patching forcibly loads the framework referenced, using hooks defers loading until it's actually needed.
8
+ #
9
+ # @safety
10
+ # While using lazy load hooks is recommended, it changes the order in which is code is loaded and may reveal
11
+ # load order dependency bugs.
12
+ #
13
+ # @example
14
+ #
15
+ # # bad
16
+ # ActiveRecord::Base.include(MyClass)
17
+ #
18
+ # # good
19
+ # ActiveSupport.on_load(:active_record) { include MyClass }
20
+ class ActiveSupportOnLoad < Base
21
+ extend AutoCorrector
22
+
23
+ MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
24
+ RESTRICT_ON_SEND = %i[prepend include extend].freeze
25
+ LOAD_HOOKS = {
26
+ 'ActionCable' => 'action_cable',
27
+ 'ActionCable::Channel::Base' => 'action_cable_channel',
28
+ 'ActionCable::Connection::Base' => 'action_cable_connection',
29
+ 'ActionCable::Connection::TestCase' => 'action_cable_connection_test_case',
30
+ 'ActionController::API' => 'action_controller',
31
+ 'ActionController::Base' => 'action_controller',
32
+ 'ActionController::TestCase' => 'action_controller_test_case',
33
+ 'ActionDispatch::IntegrationTest' => 'action_dispatch_integration_test',
34
+ 'ActionDispatch::Request' => 'action_dispatch_request',
35
+ 'ActionDispatch::Response' => 'action_dispatch_response',
36
+ 'ActionDispatch::SystemTestCase' => 'action_dispatch_system_test_case',
37
+ 'ActionMailbox::Base' => 'action_mailbox',
38
+ 'ActionMailbox::InboundEmail' => 'action_mailbox_inbound_email',
39
+ 'ActionMailbox::Record' => 'action_mailbox_record',
40
+ 'ActionMailbox::TestCase' => 'action_mailbox_test_case',
41
+ 'ActionMailer::Base' => 'action_mailer',
42
+ 'ActionMailer::TestCase' => 'action_mailer_test_case',
43
+ 'ActionText::Content' => 'action_text_content',
44
+ 'ActionText::Record' => 'action_text_record',
45
+ 'ActionText::RichText' => 'action_text_rich_text',
46
+ 'ActionView::Base' => 'action_view',
47
+ 'ActionView::TestCase' => 'action_view_test_case',
48
+ 'ActiveJob::Base' => 'active_job',
49
+ 'ActiveJob::TestCase' => 'active_job_test_case',
50
+ 'ActiveRecord::Base' => 'active_record',
51
+ 'ActiveStorage::Attachment' => 'active_storage_attachment',
52
+ 'ActiveStorage::Blob' => 'active_storage_blob',
53
+ 'ActiveStorage::Record' => 'active_storage_record',
54
+ 'ActiveStorage::VariantRecord' => 'active_storage_variant_record',
55
+ 'ActiveSupport::TestCase' => 'active_support_test_case'
56
+ }.freeze
57
+
58
+ def on_send(node)
59
+ receiver, method, arguments = *node # rubocop:disable InternalAffairs/NodeDestructuring
60
+ return unless receiver && (hook = LOAD_HOOKS[receiver.const_name])
61
+
62
+ preferred = "ActiveSupport.on_load(:#{hook}) { #{method} #{arguments.source} }"
63
+ add_offense(node, message: format(MSG, prefer: preferred, current: node.source)) do |corrector|
64
+ corrector.replace(node, preferred)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -53,10 +53,7 @@ module RuboCop
53
53
  private
54
54
 
55
55
  def index_range(pair_node)
56
- range_with_surrounding_comma(
57
- range_with_surrounding_space(range: pair_node.loc.expression, side: :left),
58
- :left
59
- )
56
+ range_with_surrounding_comma(range_with_surrounding_space(pair_node.loc.expression, side: :left), :left)
60
57
  end
61
58
  end
62
59
  end
@@ -63,8 +63,7 @@ module RuboCop
63
63
 
64
64
  MSG_NIL_OR_EMPTY = 'Use `%<prefer>s` instead of `%<current>s`.'
65
65
  MSG_NOT_PRESENT = 'Use `%<prefer>s` instead of `%<current>s`.'
66
- MSG_UNLESS_PRESENT = 'Use `if %<prefer>s` instead of ' \
67
- '`%<current>s`.'
66
+ MSG_UNLESS_PRESENT = 'Use `if %<prefer>s` instead of `%<current>s`.'
68
67
  RESTRICT_ON_SEND = %i[!].freeze
69
68
 
70
69
  # `(send nil $_)` is not actually a valid match for an offense. Nodes
@@ -111,25 +111,13 @@ module RuboCop
111
111
  remove_timestamps
112
112
  ].freeze
113
113
 
114
- MYSQL_COMBINABLE_TRANSFORMATIONS = %i[
115
- rename
116
- index
117
- remove_index
118
- ].freeze
114
+ MYSQL_COMBINABLE_TRANSFORMATIONS = %i[rename index remove_index].freeze
119
115
 
120
- MYSQL_COMBINABLE_ALTER_METHODS = %i[
121
- rename_column
122
- add_index
123
- remove_index
124
- ].freeze
116
+ MYSQL_COMBINABLE_ALTER_METHODS = %i[rename_column add_index remove_index].freeze
125
117
 
126
- POSTGRESQL_COMBINABLE_TRANSFORMATIONS = %i[
127
- change_default
128
- ].freeze
118
+ POSTGRESQL_COMBINABLE_TRANSFORMATIONS = %i[change_default].freeze
129
119
 
130
- POSTGRESQL_COMBINABLE_ALTER_METHODS = %i[
131
- change_column_default
132
- ].freeze
120
+ POSTGRESQL_COMBINABLE_ALTER_METHODS = %i[change_column_default].freeze
133
121
 
134
122
  def on_def(node)
135
123
  return unless support_bulk_alter?
@@ -186,8 +174,7 @@ module RuboCop
186
174
  options = node.arguments[1]
187
175
  return false unless options
188
176
 
189
- options.hash_type? &&
190
- options.keys.any? { |key| key.sym_type? && key.value == :bulk }
177
+ options.hash_type? && options.keys.any? { |key| key.sym_type? && key.value == :bulk }
191
178
  end
192
179
 
193
180
  def database
@@ -237,8 +224,7 @@ module RuboCop
237
224
  end
238
225
 
239
226
  def call_to_combinable_alter_method?(child_node)
240
- child_node.send_type? &&
241
- combinable_alter_methods.include?(child_node.method_name)
227
+ child_node.send_type? && combinable_alter_methods.include?(child_node.method_name)
242
228
  end
243
229
 
244
230
  def combinable_alter_methods
@@ -93,7 +93,11 @@ module RuboCop
93
93
  end
94
94
 
95
95
  def offense_range(node)
96
- end_pos = node.parent&.block_type? ? node.parent.loc.expression.end_pos : node.loc.expression.end_pos
96
+ end_pos = if node.parent&.block_type? && node.parent&.send_node == node
97
+ node.parent.loc.expression.end_pos
98
+ else
99
+ node.loc.expression.end_pos
100
+ end
97
101
 
98
102
  range_between(node.loc.selector.begin_pos, end_pos)
99
103
  end
@@ -37,9 +37,7 @@ module RuboCop
37
37
  return if node.arguments.count >= 3
38
38
 
39
39
  first_argument = node.first_argument
40
- return if !first_argument ||
41
- allowed_argument?(first_argument) ||
42
- corrected_ancestor?(node)
40
+ return if !first_argument || allowed_argument?(first_argument) || corrected_ancestor?(node)
43
41
 
44
42
  preferred_method = node.first_argument.value.to_s.underscore
45
43
  message = format(MSG, preferred_method: preferred_method, current_argument: first_argument.source)
@@ -53,22 +53,17 @@ module RuboCop
53
53
  class Date < Base
54
54
  include ConfigurableEnforcedStyle
55
55
 
56
- MSG = 'Do not use `Date.%<method_called>s` without zone. Use ' \
57
- '`Time.zone.%<day>s` instead.'
56
+ MSG = 'Do not use `Date.%<method_called>s` without zone. Use `Time.zone.%<day>s` instead.'
58
57
 
59
- MSG_SEND = 'Do not use `%<method>s` on Date objects, because they ' \
60
- 'know nothing about the time zone in use.'
58
+ MSG_SEND = 'Do not use `%<method>s` on Date objects, because they know nothing about the time zone in use.'
61
59
 
62
60
  RESTRICT_ON_SEND = %i[to_time to_time_in_current_zone].freeze
63
61
 
64
62
  BAD_DAYS = %i[today current yesterday tomorrow].freeze
65
63
 
66
- DEPRECATED_METHODS = [
67
- { deprecated: 'to_time_in_current_zone', relevant: 'in_time_zone' }
68
- ].freeze
64
+ DEPRECATED_METHODS = [{ deprecated: 'to_time_in_current_zone', relevant: 'in_time_zone' }].freeze
69
65
 
70
- DEPRECATED_MSG = '`%<deprecated>s` is deprecated. ' \
71
- 'Use `%<relevant>s` instead.'
66
+ DEPRECATED_MSG = '`%<deprecated>s` is deprecated. Use `%<relevant>s` instead.'
72
67
 
73
68
  def on_const(node)
74
69
  mod, klass = *node.children
@@ -93,15 +93,12 @@ module RuboCop
93
93
  return false if arg_array.size != argument_array.size
94
94
 
95
95
  arg_array.zip(argument_array).all? do |arg, argument|
96
- arg.arg_type? &&
97
- argument.lvar_type? &&
98
- arg.children == argument.children
96
+ arg.arg_type? && argument.lvar_type? && arg.children == argument.children
99
97
  end
100
98
  end
101
99
 
102
100
  def method_name_matches?(method_name, body)
103
- method_name == body.method_name ||
104
- (include_prefix_case? && method_name == prefixed_method_name(body))
101
+ method_name == body.method_name || (include_prefix_case? && method_name == prefixed_method_name(body))
105
102
  end
106
103
 
107
104
  def include_prefix_case?