Class: RuboCop::Cop::Rails::WhereNotWithMultipleConditions

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb

Overview

Identifies calls to ‘where.not` with multiple hash arguments.

The behavior of ‘where.not` changed in Rails 6.1. Prior to the change, `.where.not(trashed: true, role: ’admin’)‘ evaluated to `WHERE trashed != TRUE AND role != ’admin’‘. From Rails 6.1 onwards, this executes the query `WHERE NOT (trashed == TRUE AND roles == ’admin’)‘.

Examples:

# bad
User.where.not(trashed: true, role: 'admin')
User.where.not(trashed: true, role: ['moderator', 'admin'])
User.joins(:posts).where.not(posts: { trashed: true, title: 'Rails' })

# good
User.where.not(trashed: true)
User.where.not(role: ['moderator', 'admin'])
User.where.not(trashed: true).where.not(role: ['moderator', 'admin'])
User.where.not('trashed = ? OR role = ?', true, 'admin')

Constant Summary collapse

MSG =
'Use a SQL statement instead of `where.not` with multiple conditions.'
RESTRICT_ON_SEND =
%i[not].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



33
34
35
36
37
38
39
40
41
42
# File 'lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb', line 33

def on_send(node)
  where_not_call?(node) do |args|
    next unless args[0]&.hash_type?
    next unless multiple_arguments_hash? args[0]

    range = node.receiver.loc.selector.with(end_pos: node.source_range.end_pos)

    add_offense(range)
  end
end