diff --git a/changelog/fix_a_false_positive_for_rails_find_each.md b/changelog/fix_a_false_positive_for_rails_find_each.md new file mode 100644 index 0000000000..94154cefe9 --- /dev/null +++ b/changelog/fix_a_false_positive_for_rails_find_each.md @@ -0,0 +1 @@ +* [#551](https://github.com/rubocop/rubocop-rails/issues/551): Fix a false positive for `Rails/FindEach` when using `model.errors.where` in Rails 6.1. ([@koic][]) diff --git a/lib/rubocop/cop/rails/find_each.rb b/lib/rubocop/cop/rails/find_each.rb index 328d98c0d2..d7cfb4d241 100644 --- a/lib/rubocop/cop/rails/find_each.rb +++ b/lib/rubocop/cop/rails/find_each.rb @@ -43,9 +43,20 @@ def on_send(node) private def ignored?(node) + return true if active_model_error_where?(node.receiver) + method_chain = node.each_node(:send).map(&:method_name) + (cop_config['IgnoredMethods'].map(&:to_sym) & method_chain).any? end + + def active_model_error_where?(node) + node.method?(:where) && active_model_error?(node.receiver) + end + + def active_model_error?(node) + node.send_type? && node.method?(:errors) + end end end end diff --git a/spec/rubocop/cop/rails/find_each_spec.rb b/spec/rubocop/cop/rails/find_each_spec.rb index 71bb1261c8..8ec27e1943 100644 --- a/spec/rubocop/cop/rails/find_each_spec.rb +++ b/spec/rubocop/cop/rails/find_each_spec.rb @@ -42,6 +42,13 @@ expect_no_offenses('User.all.find_each { |u| u.x }') end + # Active Model Errors slice from the new query interface introduced in Rails 6.1. + it 'does not register an offense when using `model.errors.where`' do + expect_no_offenses(<<~RUBY) + model.errors.where(:title).each { |error| do_something(error) } + RUBY + end + it 'auto-corrects each to find_each' do expect_offense(<<~RUBY) User.all.each { |u| u.x }