class RuboCop::Cop::Rails::WhereNotWithMultipleConditions
User.where.not(‘trashed = ? OR role = ?’, true, ‘admin’)
User.where.not(trashed: true).where.not(role: [‘moderator’, ‘admin’])
User.where.not(role: [‘moderator’, ‘admin’])
User.where.not(trashed: true)
# good
User.joins(:posts).where.not(posts: { trashed: true, title: ‘Rails’ })
User.where.not(trashed: true, role: [‘moderator’, ‘admin’])
User.where.not(trashed: true, role: ‘admin’)
# bad
@example
`WHERE NOT (trashed == TRUE AND roles == ‘admin’)‘.
From Rails 6.1 onwards, this executes the query
`WHERE trashed != TRUE AND role != ’admin’‘.
`.where.not(trashed: true, role: ’admin’)‘ evaluated to
The behavior of `where.not` changed in Rails 6.1. Prior to the change,
Identifies calls to `where.not` with multiple hash arguments.
def multiple_arguments_hash?(hash)
def multiple_arguments_hash?(hash) return true if hash.pairs.size >= 2 return false unless hash.values[0]&.hash_type? multiple_arguments_hash?(hash.values[0]) end
def on_send(node)
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