edge badge
Skip to Content Skip to Search

WhereChain objects act as placeholder for queries in which where does not have any parameter. In this case, where must be chained with not to return a new relation.

Methods
A
M
N

Class Public methods

new(scope)

# File activerecord/lib/active_record/relation/query_methods.rb, line 16
def initialize(scope)
  @scope = scope
end

Instance Public methods

associated(*associations)

Returns a new relation with joins and where clause to identify associated relations.

For example, posts that are associated to a related author:

Post.where.associated(:author)
# SELECT "posts".* FROM "posts"
# INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
# WHERE "authors"."id" IS NOT NULL

Additionally, multiple relations can be combined. This will return posts associated to both an author and any comments:

Post.where.associated(:author, :comments)
# SELECT "posts".* FROM "posts"
# INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
# INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
# WHERE "authors"."id" IS NOT NULL AND "comments"."id" IS NOT NULL
# File activerecord/lib/active_record/relation/query_methods.rb, line 69
def associated(*associations)
  associations.each do |association|
    reflection = @scope.klass._reflect_on_association(association)
    @scope.joins!(association)
    self.not(reflection.table_name => { reflection.association_primary_key => nil })
  end

  @scope
end

missing(*associations)

Returns a new relation with left outer joins and where clause to identify missing relations.

For example, posts that are missing a related author:

Post.where.missing(:author)
# SELECT "posts".* FROM "posts"
# LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id"
# WHERE "authors"."id" IS NULL

Additionally, multiple relations can be combined. This will return posts that are missing both an author and any comments:

Post.where.missing(:author, :comments)
# SELECT "posts".* FROM "posts"
# LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id"
# LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id"
# WHERE "authors"."id" IS NULL AND "comments"."id" IS NULL
# File activerecord/lib/active_record/relation/query_methods.rb, line 97
def missing(*associations)
  associations.each do |association|
    reflection = @scope.klass._reflect_on_association(association)
    @scope.left_outer_joins!(association)
    @scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
  end

  @scope
end

not(opts, *rest)

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')

User.where.not(name: "Jon", role: "admin")
# SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
# File activerecord/lib/active_record/relation/query_methods.rb, line 43
def not(opts, *rest)
  where_clause = @scope.send(:build_where_clause, opts, rest)

  @scope.where_clause += where_clause.invert

  @scope
end