From a5fa36d98ec59c469211745370c0f406f08d5a03 Mon Sep 17 00:00:00 2001 From: Brian Hawley Date: Wed, 6 Jul 2022 10:10:53 -0700 Subject: [PATCH] No correction for `errors.details[:n] << v` Fixes for Rails/DeprecatedActiveModelErrorsMethods: - Fixed a bad autocorrection of errors.details[:name] << value. There isn't really a correct replacement for this one. - Did some refactors prompted by rubocop complaints. - Fixed a misspelling of autocorrectable. - Added missing correction assertions to test cases. --- ...x_deprecated_errors_bad_details_autocorrection.md | 1 + .../rails/deprecated_active_model_errors_methods.rb | 11 +++++++++-- .../deprecated_active_model_errors_methods_spec.rb | 12 ++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 changelog/fix_deprecated_errors_bad_details_autocorrection.md 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 e2c9d79e93..b0ea0f2247 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) + receiver = node.receiver.receiver + !AUTOCORRECTABLE_METHODS.include?(node.method_name) || ( + 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 41e1219594..c82019c06b 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 @@ -108,6 +108,8 @@ user.errors.details[:name] << {} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid manipulating ActiveModel errors as hash directly. RUBY + + expect_no_corrections end context 'when assigning' do @@ -131,6 +133,14 @@ def expect_offense_if_model_file(code, file_path) end end + def expect_correction_if_model_file(code, file_path) + expect_correction(code) if file_path.include?('/models/') + end + + def expect_no_corrections_if_model_file(file_path) + expect_no_corrections if file_path.include?('/models/') + end + context 'when modifying errors' do it 'registers an offense for model file' do expect_offense_if_model_file(<<~RUBY, file_path) @@ -189,6 +199,8 @@ def expect_offense_if_model_file(code, 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