diff --git a/changelog/fix_deprecated_errors_bad_details_autocorrection.md b/changelog/fix_deprecated_errors_bad_details_autocorrection.md new file mode 100644 index 0000000000..818b5950a1 --- /dev/null +++ b/changelog/fix_deprecated_errors_bad_details_autocorrection.md @@ -0,0 +1 @@ +* [#741](https://github.com/rubocop/rubocop-rails/pull/741): Fix a bad autocorrection for `errors.details[:name] << value` in Rails/DeprecatedActiveModelErrorsMethods. ([@BrianHawley][]) diff --git a/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb b/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb index f115174158..0fa054ed02 100644 --- a/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +++ b/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb @@ -37,7 +37,7 @@ class DeprecatedActiveModelErrorsMethods < Base extend AutoCorrector MSG = 'Avoid manipulating ActiveModel errors as hash directly.' - AUTOCORECTABLE_METHODS = %i[<< clear keys].freeze + AUTOCORRECTABLE_METHODS = %i[<< clear keys].freeze MANIPULATIVE_METHODS = Set[ *%i[ @@ -109,7 +109,7 @@ def on_send(node) next if node.method?(:keys) && target_rails_version <= 6.0 add_offense(node) do |corrector| - next unless AUTOCORECTABLE_METHODS.include?(node.method_name) + next if skip_autocorrect?(node) autocorrect(corrector, node) end @@ -118,6 +118,13 @@ def on_send(node) private + def skip_autocorrect?(node) + return true unless AUTOCORRECTABLE_METHODS.include?(node.method_name) + return false unless (receiver = node.receiver.receiver) + + receiver.send_type? && receiver.method?(:details) && node.method?(:<<) + end + def autocorrect(corrector, node) receiver = node.receiver diff --git a/spec/rubocop/cop/rails/deprecated_active_model_errors_methods_spec.rb b/spec/rubocop/cop/rails/deprecated_active_model_errors_methods_spec.rb index 1ccd7f1e31..bcac8a8c89 100644 --- a/spec/rubocop/cop/rails/deprecated_active_model_errors_methods_spec.rb +++ b/spec/rubocop/cop/rails/deprecated_active_model_errors_methods_spec.rb @@ -135,6 +135,8 @@ user.errors.details[:name] << {} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid manipulating ActiveModel errors as hash directly. RUBY + + expect_no_corrections end context 'when assigning' do @@ -318,6 +320,8 @@ def expect_no_corrections_if_model_file(file_path) errors.details[:name] << {} ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid manipulating ActiveModel errors as hash directly. RUBY + + expect_no_corrections_if_model_file(file_path) end context 'when assigning' do