Method: ActiveRecord::QueryMethods::WhereChain#not

Defined in:
lib/active_record/relation/query_methods.rb

#not(opts, *rest) ⇒ Object

Returns a new relation expressing WHERE + NOT condition according to the conditions in the arguments.

#not accepts conditions as a string, array, or hash. See QueryMethods#where for more details on each format.

User.where.not("name = 'Jon'")
# SELECT * FROM users WHERE NOT (name = 'Jon')

User.where.not(["name = ?", "Jon"])
# SELECT * FROM users WHERE NOT (name = 'Jon')

User.where.not(name: "Jon")
# SELECT * FROM users WHERE name != 'Jon'

User.where.not(name: nil)
# SELECT * FROM users WHERE name IS NOT NULL

User.where.not(name: %w(Ko1 Nobu))
# SELECT * FROM users WHERE name NOT IN ('Ko1', 'Nobu')


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/active_record/relation/query_methods.rb', line 44

def not(opts, *rest)
  opts = sanitize_forbidden_attributes(opts)

  where_clause = @scope.send(:where_clause_factory).build(opts, rest)

  @scope.references!(PredicateBuilder.references(opts)) if Hash === opts

  if not_behaves_as_nor?(opts)
    ActiveSupport::Deprecation.warn(<<~MSG.squish)
      NOT conditions will no longer behave as NOR in Rails 6.1.
      To continue using NOR conditions, NOT each condition individually
      (`#{
        opts.flat_map { |key, value|
          if value.is_a?(Hash) && value.size > 1
            value.map { |k, v| ".where.not(#{key.inspect} => { #{k.inspect} => ... })" }
          else
            ".where.not(#{key.inspect} => ...)"
          end
        }.join
      }`).
    MSG
    @scope.where_clause += where_clause.invert(:nor)
  else
    @scope.where_clause += where_clause.invert
  end

  @scope
end