Queries
This page covers the filtering and relation-modification vocabulary that builds on the basics in Relations. Everything here returns a new relation — the original is never mutated.
where shorthands
where(%conditions) accepts several value shapes:
| Shape | SQL emitted |
|---|---|
where({col => $value}) |
col = ? |
where({col => Nil}) |
col IS NULL |
where({col => [a, b, c]}) |
col IN (?, ?, ?) |
where({col => 1..10}) |
col BETWEEN ? AND ? |
where({assoc => $instance}) |
assoc_id = ? (uses $instance.id) |
1 2 3 4 | |
where.not
where.not(%conditions) adds a negated condition. Nil, ranges, and arrays
work the same as the positive form.
1 2 3 4 | |
where.missing and where.associated
For relations through associations, where.missing(:assoc) finds records
with no associated rows; where.associated(:assoc) finds those that have at
least one. Both work over belongs_to, has_many, and has_many :through.
1 2 3 | |
Model.associated(:assoc) is a class-level shortcut for the common case.
excluding
excluding(*@records-or-ids) removes specific rows from the result set,
mirroring WHERE id NOT IN (...).
1 2 3 | |
It composes naturally:
1 | |
or and and
or(other_relation) and and(other_relation) combine WHERE clauses across
two relations. The result is a single SQL query with the conditions wrapped
in the right boolean structure.
1 2 | |
merge
merge(other_relation) folds another relation's clauses into this one.
Last-wins semantics: other takes precedence for limit, offset,
distinct, and readonly. where, order, joins, and similar additive
clauses are concatenated.
1 2 3 4 5 6 | |
rewhere
rewhere(%conditions) replaces any prior where conditions on the same
columns. Useful when narrowing-then-broadening.
1 2 | |
unscope
unscope(:scope) surgically removes a single relation dimension:
1 2 3 4 | |
You can also drop a single where condition by column:
1 2 3 | |